
Se vocĂȘ estiver trabalhando com o ambiente Kubernetes, provavelmente utilizarĂĄ vĂĄrias ferramentas de modelagem existentes, algumas delas fazendo parte de gerenciadores de pacotes, como Helm ou Ksonnet , ou apenas linguagens de modelagem (Jinja2, modelo Go etc.). Todos eles tĂȘm suas prĂłprias desvantagens, alĂ©m de vantagens, e vamos analisĂĄ-los e escrever nossa prĂłpria ferramenta que tentarĂĄ combinar os melhores recursos.
EntĂŁo, por que nĂŁo Helm?
Existem vårios artigos que criticam o Helm (por exemplo, apenas um deles: pense duas vezes antes de usar o Helm ). O principal problema do Helm é que ele funciona com representaçÔes de strings e os manifestos do Kubernetes são objetos (json) . O verdadeiro inferno para um desenvolvedor de gråficos Helm começa quando ele precisa calcular recuos para um manifesto yaml
, Ă s vezes parece com isso (Ă© um exemplo real do meu grĂĄfico):
spec: jobTemplate: spec: template: spec: containers: - name: my-awesome-container resources: {{ toYaml .Values.resources | indent 14 }}

Hoje, porĂ©m, o Helm Ă© de fato o padrĂŁo para o empacotamento de aplicativos Kubernetes. A principal vantagem do Helm Ă© uma grande comunidade e um grande nĂșmero de repositĂłrios pĂșblicos com grĂĄficos. E, recentemente, os desenvolvedores do Helm anunciaram um hub Helm . O Helm hoje Ă© como o Docker - nĂŁo Ă© o Ășnico, mas tem comunidade e suporte.
Existem mudanças promissoras no lançamento do Helm 3, mas ninguém sabe quando poderia ser.
Para concluir, as vantagens do Helm:
- Grande comunidade e vĂĄrios grĂĄficos pĂșblicos
- (Relativamente) sintaxe amigĂĄvel ao ser humano. Pelo menos Ă© o modelo yaml + go;)
Desvantagens:
- Trabalhando com strings e nĂŁo objetos
- NĂșmero limitado de operadores e funçÔes que vocĂȘ pode usar
OK, entĂŁo talvez Ksonnet?
Se vocĂȘ estĂĄ comparando o Helm ao Ksonnet, o Ășltimo possui uma enorme vantagem, a saber, funciona com objetos. O Ksonnet Ă© uma ferramenta baseada na linguagem de modelagem JSON Jsonnet. Outro recurso interessante sobre o Ksonnet Ă© que ele possui bibliotecas Jsonnet compatĂveis com a API do Kubernetes que vocĂȘ pode importar para o seu modelo e trabalhar com objetos do Kubernetes, como em qualquer linguagem OOP:
local k = import "k.libsonnet"; local deployment = k.apps.v1beta1.deployment; local appDeployment = deployment .new( params.name, params.replicas, container .new(params.name, params.image) .withPorts(containerPort.new(targetPort)), labels);
Parece impressionante, nĂŁo Ă©?
Ă um pouco menos interessante quando vocĂȘ trabalha nĂŁo com objetos API, mas apenas com objetos json importados do arquivo yaml
/ json
:
{ global: {}, components: { "deployment-nginx-deployment-dkecx"+: { spec+: { replicas: 10, template+: { spec+: { containers+: [ { name: "nginx", image: "nginx:latest", ports: [ { containerPort: 80, }, ], }, ], }, }, }, }, }, }
Mas ainda Ă© algo e Ă© melhor do que trabalhar com strings no Helm. A desvantagem do Ksonnet Ă© que ele possui uma comunidade menor e menos pacotes que o Helm (embora vocĂȘ possa importar grĂĄficos do Helm para o seu projeto Ksonnet, mas vocĂȘ estarĂĄ trabalhando com eles como objetos json, nĂŁo como objetos da biblioteca jsonnet). E, como resultado de uma comunidade e contribuição menores, faltam alguns recursos ao tentar escrever seu prĂłprio grĂĄfico. Um deles eu experimentei: vocĂȘ sabe que no Helm vocĂȘ pode criar um ConfigMap
partir de um diretório que contém vårios arquivos de configuração desta maneira:
apiVersion: v1 kind: ConfigMap metadata: name: conf data: {{- (.Files.Glob "foo/*").AsConfig | nindent 2 }}
VocĂȘ pode imaginar minha frustração quando descobri que nĂŁo existe esse recurso no Ksonnet. Existem soluçÔes alternativas. Mas o ponto Ă© que Ă© apenas um exemplo da situação em que vocĂȘ estĂĄ escrevendo seu grĂĄfico com alegria e, de repente, a falta de algum recurso o impede no meio do caminho.
No total, vantagens do Ksonnet:
- Trabalhando com objetos
- Bibliotecas Jsonnet compatĂveis com API do Kubernetes
- Suporte à importação de gråficos de leme
Desvantagens:
- Comunidade menor e menor nĂșmero de pacotes nativos do Ksonnet
- Falta de algumas funcionalidades que vocĂȘ pode usar no Helm
- Nova sintaxe => aumento do tempo de aprendizado => aumento do fator de barramento
- Ăs vezes, a sintaxe pode se tornar feia e menos legĂvel por humanos (especialmente quando vocĂȘ faz soluçÔes alternativas por falta de recursos)
Aqui estão alguns critérios para a ferramenta de modelagem "ideal":
- Deve funcionar com objetos, nĂŁo com strings
- Ele deve ter a capacidade de trabalhar com objetos compatĂveis com a API do Kubernetes
- Deve ter um conjunto decente de funçÔes para trabalhar com strings
- Deve funcionar bem com os formatos json e yaml
- Deve ser amigĂĄvel ao ser humano
- Deveria ser simples
- Deve ter a capacidade de importar grĂĄficos Helm existentes (porque isso Ă© realidade e queremos fazer uso da comunidade Helm)
Isso é o suficiente por enquanto. Examinei esta lista na minha cabeça e pensei: tudo bem, por que não tentar o Python? Vamos ver se ele se encaixa nos nossos critérios:
- Trabalhe com objetos, nĂŁo cordas . Sim, podemos usar tipos de
dict
e list
para isso. - Possibilidade de trabalhar com objetos compatĂveis com a API do Kubernetes . Sim,
from kubernetes import client
- Tenha um conjunto decente de funçÔes para trabalhar com strings . Muito!
- Trabalhe bem com os formatos json e yaml . Muito bem.
- Amigo do Homem NĂŁo brinca.
- Simples Sim
- Capacidade de importar grĂĄficos Helm existentes . Vamos nos adicionar.
Ok, parece promissor. Decidi escrever uma ferramenta simples de modelagem no topo da biblioteca cliente oficial do Python para o kubernetes e agora deixe-me mostrar o que saiu dela.
Conheça karavel
Não hå nada de especial ou complicado nessa ferramenta. Acabei de pegar a biblioteca Kubernetes (que me permitiu trabalhar com objetos Kubernetes) e escrevi algumas funcionalidades båsicas para gråficos Helm existentes (para que alguém pudesse buscå-los e adicionå-los ao seu próprio gråfico). Então, vamos fazer um tour.
Primeiro, esta ferramenta estĂĄ acessĂvel no repositĂłrio do Github e vocĂȘ pode encontrar um diretĂłrio com exemplos lĂĄ.
InĂcio rĂĄpido com a imagem do Docker
Se vocĂȘ quiser experimentar, a maneira mais simples Ă© usar esta imagem do docker :
$ docker run greegorey/karavel -h usage: karavelcli.py [-h] subcommand ... optional arguments: -h, --help show this help message and exit list of subcommands: subcommand template generates manifests from template ensure ensure helm dependencies
Obviamente, se vocĂȘ deseja modelar grĂĄficos, precisarĂĄ montar o diretĂłrio do seu grĂĄfico:
$ cd example $ docker run -v $PWD:/chart greegorey/karavel template .
EntĂŁo, vamos dar uma olhada na estrutura do grĂĄfico. Ă muito semelhante a um dos Helm:
$ cd example $ tree . . âââ dependencies âââ prod.yaml âââ requirements.yaml âââ templates â âââ custom-resource.py â âââ deployment.py â âââ service-helm.py âââ values.yaml 2 directories, 6 files
Como o Helm, ele possui o arquivo requirements.yaml
com o mesmo layout:
dependencies: - name: mysql version: 0.13.1 repository: https://kubernetes-charts.storage.googleapis.com/
Aqui, vocĂȘ apenas lista as dependĂȘncias do Helm que deseja importar para o seu grĂĄfico. As dependĂȘncias vĂŁo para o diretĂłrio de dependencies
. Para buscĂĄ-los ou atualizĂĄ-los, use o comando ensure
:
$ karavel ensure .
Depois disso, o diretĂłrio de dependencies
ficarĂĄ assim:
$ tree dependencies dependencies âââ mysql-0.13.1 âââ mysql âââ Chart.yaml âââ README.md âââ templates â âââ NOTES.txt â âââ _helpers.tpl â âââ configurationFiles-configmap.yaml â âââ deployment.yaml â âââ initializationFiles-configmap.yaml â âââ pvc.yaml â âââ secrets.yaml â âââ svc.yaml â âââ tests â âââ test-configmap.yaml â âââ test.yaml âââ values.yaml 4 directories, 13 files
Agora, depois de garantirmos nossas dependĂȘncias, vamos dar uma olhada nos modelos. Primeiro, criamos uma implantação simples do nginx:
from kubernetes import client from karavel.helpers import Values def template(): values = Values().values
Portanto, para que o modelo seja vĂĄlido, vocĂȘ precisa ter a função template()
que retorna um Ășnico objeto Kubernetes ou uma list
/ tuple
deles. VocĂȘ pode encontrar a lista de objetos de API para o cliente Python aqui .
Como vocĂȘ pode ver, o cĂłdigo Ă© limpo, simples, legĂvel. VocĂȘ pode se perguntar de onde vem o values.nginx.image.repository
? Ele obtĂ©m valores dos arquivos de valores que vocĂȘ passa ao modelar o grĂĄfico, assim como no Helm: karavel template -f one.yaml --values two.yaml
. Vamos dar uma olhada neles mais tarde.
Ok, e os grĂĄficos Helm?
Agora, criamos nossa própria implantação. Mas e se quisermos importar o gråfico Helm ou parte dele? Vamos dar uma olhada em templates/service-helm.py
:
from kubernetes import client from karavel.helm import HelmChart from karavel.helpers import Values def template(): values = Values().values
Simples, né? Observe esta linha: service = chart.get(name='svc', obj_class=client.V1Service)
- criamos o objeto da classe yaml
arquivo Helm yaml
. Se vocĂȘ nĂŁo quiser / precisar fazer isso - sempre poderĂĄ trabalhar com apenas dict
.
E se eu quiser criar um recurso personalizado?
Bem, hå um pequeno problema com isso. A API do Kubernetes não adiciona objetos CRD à definição swagger json em /openapi/v2
, e os objetos cliente Python sĂŁo /openapi/v2
base nessa definição. Mas vocĂȘ ainda pode trabalhar facilmente com objetos de dict
. Assim:
from kubernetes import client def template(): resource = { 'apiVersion': 'stable.example.com/v1', 'kind': 'Whale', 'metadata': client.V1ObjectMeta( name='my-object', ), 'spec': { 'image': 'my-whale-image:0.0.1', 'tail': 1, 'fins': 4, } } return resource
Ainda parece bom, nĂŁo Ă©?
Posso ter valores para ambientes diferentes, por exemplo, dev / prod?
Sim vocĂȘ pode!
Vamos dar uma olhada em values.yaml
primeiro:
nginx: image: repository: nginx tag: 1.15-alpine mysql: port: 3307 protocol: TCP helm: releaseName: my-release namespace: prod imageTag: '5.7.14' service: type: NodePort
Observe a chave helm
no dict do mysql
: usamos quando especificamos valores para o grĂĄfico do helm chart chart = HelmChart(name='mysql', version='0.13.1', values=values.mysql.helm)
. Alguns grĂĄficos Helm precisam de releaseName
para nomeação de aplicativos e namespace
para polĂticas RBAC. Esses dois valores sĂŁo transmitidos ao Helm como argumentos --namespace
e NAME
no helm template
.
Agora, vocĂȘ pode especificar um arquivo adicional para prod env e modelar todos os nossos exemplos:
$ karavel template -f values.yaml -f prod.yaml . --- # Source: templates/custom-resource.py apiVersion: stable.example.com/v1 kind: Whale metadata: name: my-object spec: fins: 4 image: my-whale-image:0.0.1 tail: 1 --- # Source: templates/deployment.py apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 template: metadata: labels: app: nginx spec: containers: - image: nginx:1.14-alpine name: nginx ports: - containerPort: 80 --- # Source: templates/service-helm.py apiVersion: v1 kind: Service metadata: annotations: null labels: app: prod-release-mysql chart: mysql-0.13.1 release: prod-release-suffix name: prod-release-mysql spec: ports: - name: my-custom-port port: 3308 protocol: TCP targetPort: 39000 selector: app: prod-release-mysql type: NodePort
Depois disso, vocĂȘ pode kubeclt apply
e implantar esses objetos no cluster.
Legal! E quanto a codificação e base64?
import base64
Que tal usar o Vault para segredos?
import hvac
Buscando URLs?
import importlib
FunçÔes hash seguras?
import Crypto
VocĂȘ entendeu. Com o Python, vocĂȘ pode fazer muitas coisas com seus manifestos do Kubernetes.
Ă sĂndrome do NIH?
NĂŁo :)
Eu sou alegremente usando Helm em meus projetos atuais. Mas hå coisas que sinto falta. Também usei o Ksonnet em alguns dos meus projetos.
Gostaria de pensar nessa ferramenta como uma prova de conceito de que podemos ter ferramentas de modelagem melhores que o Helm e nĂŁo Ă© muito difĂcil desenvolvĂȘ-las usando o Python. Se houver um interesse / necessidade da comunidade em tal ferramenta, podemos juntos continuar a desenvolvĂȘ-la. Ou podemos esperar pelo lançamento do Helm 3;)
ConclusĂŁo
Eu mostrei a vocĂȘ a ferramenta de modelagem baseada em Python para o Kubernetes, que possui suporte a objetos compatĂveis com a API do Kubernetes e suporta a importação de grĂĄficos Helm. Quaisquer comentĂĄrios e discussĂ”es da comunidade sĂŁo bem-vindos e novamente bem-vindos ao repositĂłrio .
Obrigado por ler isso e tenha um bom dia!
ReferĂȘncias