Podes ler sobre o propio helmfile e exemplos do seu uso
Coñeceremos formas non obvias de describir as versións en helmfile
Digamos que temos un paquete de gráficos helm (por exemplo, digamos Postgres e algunha aplicación de backend) e varios ambientes (varios clústeres de kubernetes, varios espazos de nomes ou varios dos dous). Collemos o ficheiro helm, lemos a documentación e comezamos a describir os nosos ambientes e versións:
.
├── envs
│ ├── devel
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ └── production
│ └── values
│ ├── backend.yaml
│ └── postgres.yaml
└── helmfile.yaml
helmfile.yaml
environments:
devel:
production:
releases:
- name: postgres
labels:
app: postgres
wait: true
chart: stable/postgresql
version: 8.4.0
values:
- envs/{{ .Environment.Name }}/values/postgres.yaml
- name: backend
labels:
app: backend
wait: true
chart: private-helm-repo/backend
version: 1.0.5
needs:
- postgres
values:
- envs/{{ .Environment.Name }}/values/backend.yaml
Rematamos con 2 ambientes: desenvolver, produción - cada un contén os seus propios valores para os gráficos de lanzamento do timón. Implementarémoslles así:
helmfile -n <namespace> -e <env> apply
Diferentes versións de gráficos de timón en diferentes ambientes
E se necesitamos lanzar diferentes versións do backend a diferentes ambientes? Como parametrizar a versión do lanzamento? Os valores ambientais dispoñibles a través {{ .Values }}
helmfile.yaml
environments:
devel:
+ values:
+ - charts:
+ versions:
+ backend: 1.1.0
production:
+ values:
+ - charts:
+ versions:
+ backend: 1.0.5
...
- name: backend
labels:
app: backend
wait: true
chart: private-helm-repo/backend
- version: 1.0.5
+ version: {{ .Values.charts.versions.backend }}
...
Diferente conxunto de aplicacións en diferentes ambientes
Xenial, pero que pasa se non o necesitamos production
lanzar postgres, porque sabemos que non necesitamos empurrar a base de datos a k8s e que temos á venda un marabilloso clúster de postgres separado? Para solucionar este problema temos etiquetas
helmfile -n <namespace> -e devel apply
helmfile -n <namespace> -e production -l app=backend apply
Isto é xenial, pero persoalmente prefiro describir que aplicacións implementar no entorno non usando argumentos de lanzamento, senón na descrición dos propios entornos. Que facer? Pode colocar as descricións de versións nun cartafol separado, crear unha lista das versións necesarias na descrición do ambiente e "recoller" só as versións necesarias, ignorando o resto
.
├── envs
│ ├── devel
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ └── production
│ └── values
│ ├── backend.yaml
│ └── postgres.yaml
+ ├── releases
+ │ ├── backend.yaml
+ │ └── postgres.yaml
└── helmfile.yaml
helmfile.yaml
environments:
devel:
values:
- charts:
versions:
backend: 1.1.0
- apps:
- postgres
- backend
production:
values:
- charts:
versions:
backend: 1.0.5
- apps:
- backend
- releases:
- - name: postgres
- labels:
- app: postgres
- wait: true
- chart: stable/postgresql
- version: 8.4.0
- values:
- - envs/{{ .Environment.Name }}/values/postgres.yaml
- - name: backend
- labels:
- app: backend
- wait: true
- chart: private-helm-repo/backend
- version: {{ .Values.charts.versions.backend }}
- needs:
- - postgres
- values:
- - envs/{{ .Environment.Name }}/values/backend.yaml
+ ---
+ bases:
+ {{- range .Values.apps }}
+ - releases/{{ . }}.yaml
+ {{- end }}
releases/postgres.yaml
releases:
- name: postgres
labels:
app: postgres
wait: true
chart: stable/postgresql
version: 8.4.0
values:
- envs/{{ .Environment.Name }}/values/postgres.yaml
releases/backend.yaml
releases:
- name: backend
labels:
app: backend
wait: true
chart: private-helm-repo/backend
version: {{ .Values.charts.versions.backend }}
needs:
- postgres
values:
- envs/{{ .Environment.Name }}/values/backend.yaml
A nota
Ao usar bases:
é necesario utilizar o separador de yaml ---
, para que poida modelo lanzamentos (e outras partes, como helmDefaults) con valores de ambientes
Neste caso, a versión de postgres nin sequera se incluirá na descrición para a produción. Moi cómodo!
Valores globais anulables para versións
Por suposto, é xenial que poidas establecer valores para os gráficos de timón para cada ambiente, pero que pasa se temos varios ambientes descritos e queremos, por exemplo, establecer o mesmo para todos. affinity
, pero non queremos configuralo por defecto nos propios gráficos, que se almacenan en grelos.
Neste caso, para cada versión poderiamos especificar 2 ficheiros con valores: o primeiro con valores predeterminados, que determinará os valores do propio gráfico, e o segundo con valores para o entorno, que á súa vez anulará o os predeterminados.
.
├── envs
+ │ ├── default
+ │ │ └── values
+ │ │ ├── backend.yaml
+ │ │ └── postgres.yaml
│ ├── devel
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ └── production
│ └── values
│ ├── backend.yaml
│ └── postgres.yaml
├── releases
│ ├── backend.yaml
│ └── postgres.yaml
└── helmfile.yaml
releases/backend.yaml
releases:
- name: backend
labels:
app: backend
wait: true
chart: private-helm-repo/backend
version: {{ .Values.charts.versions.backend }}
needs:
- postgres
values:
+ - envs/default/values/backend.yaml
- envs/{{ .Environment.Name }}/values/backend.yaml
envs/default/values/backend.yaml
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- backend
topologyKey: "kubernetes.io/hostname"
Definición de valores globais para gráficos de timón de todos os lanzamentos a nivel ambiental
Digamos que creamos varias entradas en varias versións; poderiamos definir manualmente para cada gráfico hosts:
, pero no noso caso o dominio é o mesmo, entón por que non poñelo nalgunha variable global e simplemente substituír o seu valor nos gráficos? Para iso, aqueles ficheiros con valores que queiramos parametrizar terán que ter a extensión .gotmpl
, para que helmfile saiba que hai que executalo a través do motor de modelos.
.
├── envs
│ ├── default
│ │ └── values
- │ │ ├── backend.yaml
- │ │ ├── postgres.yaml
+ │ │ ├── backend.yaml.gotmpl
+ │ │ └── postgres.yaml.gotmpl
│ ├── devel
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ └── production
│ └── values
│ ├── backend.yaml
│ └── postgres.yaml
├── releases
│ ├── backend.yaml
│ └── postgres.yaml
└── helmfile.yaml
helmfile.yaml
environments:
devel:
values:
- charts:
versions:
backend: 1.1.0
- apps:
- postgres
- backend
+ - global:
+ ingressDomain: k8s.devel.domain
production:
values:
- charts:
versions:
backend: 1.0.5
- apps:
- backend
+ - global:
+ ingressDomain: production.domain
---
bases:
{{- range .Values.apps }}
- releases/{{ . }}.yaml
{{- end }}
envs/default/values/backend.yaml.gotmpl
ingress:
enabled: true
paths:
- /api
hosts:
- {{ .Values.global.ingressDomain }}
envs/default/values/postgres.yaml.gotmpl
ingress:
enabled: true
paths:
- /
hosts:
- postgres.{{ .Values.global.ingressDomain }}
A nota
Obviamente, a entrada no gráfico de postgres é algo moi dubidoso, polo que este artigo dáse simplemente como un exemplo esférico no baleiro e para non introducir algunha nova versión no artigo só para describir a entrada.
Substituíndo segredos dos valores ambientais
Por analoxía co exemplo anterior, pode substituír os cifrados usando
.
├── envs
│ ├── default
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ ├── devel
│ │ ├── values
│ │ │ ├── backend.yaml
│ │ │ └── postgres.yaml
+ │ │ └── secrets.yaml
│ └── production
│ ├── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
+ │ └── secrets.yaml
├── releases
│ ├── backend.yaml
│ └── postgres.yaml
└── helmfile.yaml
helmfile.yaml
environments:
devel:
values:
- charts:
versions:
backend: 1.1.0
- apps:
- postgres
- backend
- global:
ingressDomain: k8s.devel.domain
+ secrets:
+ - envs/devel/secrets.yaml
production:
values:
- charts:
versions:
backend: 1.0.5
- apps:
- backend
- global:
ingressDomain: production.domain
+ secrets:
+ - envs/production/secrets.yaml
---
bases:
{{- range .Values.apps }}
- releases/{{ . }}.yaml
{{- end }}
envs/devel/secrets.yaml
secrets:
elastic:
password: ENC[AES256_GCM,data:hjCB,iv:Z1P6/6xBJgJoKLJ0UUVfqZ80o4L84jvZfM+uH9gBelc=,tag:dGqQlCZnLdRAGoJSj63rBQ==,type:int]
...
envs/production/secrets.yaml
secrets:
elastic:
password: ENC[AES256_GCM,data:ZB/VpTFk8f0=,iv:EA//oT1Cb5wNFigTDOz3nA80qD9UwTjK5cpUwLnEXjs=,tag:hMdIUaqLRA8zuFBd82bz6A==,type:str]
...
envs/default/values/backend.yaml.gotmpl
elasticsearch:
host: elasticsearch
port: 9200
password: {{ .Values | getOrNil "secrets.elastic.password" | default "password" }}
envs/devel/values/backend.yaml
elasticsearch:
host: elastic-0.devel.domain
envs/production/values/backend.yaml
elasticsearch:
host: elastic-0.production.domain
A nota
By the way, getOrNil
- unha función especial para os modelos go en helmfile, que, aínda que .Values.secrets
non existirá, non lanzará un erro, pero permitirá o resultado usando a función default
substituír o valor predeterminado
Conclusión
As cousas descritas parecen bastante obvias, pero a información sobre unha descrición cómoda da implementación en varios ambientes que usan helmfile é moi escasa e encántame IaC (Infraestrutura-como-Code) e quero ter unha descrición clara do estado de implementación.
Como conclusión, gustaríame engadir que as variables para o entorno predeterminado pódense, á súa vez, parametrizarse coas variables de entorno do SO dun determinado corredor desde o que se iniciará o despregamento, e así obter contornas dinámicas.
helmfile.yaml
environments:
default:
values:
- global:
clusterDomain: {{ env "CLUSTER_DOMAIN" | default "cluster.local" }}
ingressDomain: {{ env "INGRESS_DOMAIN" }}
Fonte: www.habr.com