Primeros pasos con helm

2018-12-23 | Gabriel Garrido | 7 min de lectura
Share:

Apoya este blog

Si te resulta util este contenido, considera apoyar el blog.

Introduccion

En este tutorial vamos a ver como usar Helm, el cluster de despliegue sera minikube si preferis kind or cualquier otro cluster deberia funcionar de la misma manera:

Creando el chart:

helm create hello-world

Siempre hay que tener en cuenta las restricciones de DNS a la hora de elegir nombres, ya que esto puede traer problemas despues.

Inspeccionemos el contenido, como podemos ver son recursos de kubernetes similar a los templates de go:

$ cd hello-world

charts       <--- Dependencies, charts that your chart depends on.
Chart.yaml   <--- Metadata mostly, defines the version of your chart, etc.
templates    <--- Here is where the magic happens.
values.yaml  <--- Default values file (this is used to replace in the templates at runtime)

Nota: este link explica lo basico de manejo de dependencias, tu chart puede tener varias dependencias, solo tienes que listarlas como dependencias.

El archivo values.yaml por defecto se ve asi:

replicaCount: 1

image:
  repository: nginx
  tag: stable
  pullPolicy: IfNotPresent

nameOverride: ""
fullnameOverride: ""

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  path: /
  hosts:
    - chart-example.local
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local

resources: {}
nodeSelector: {}
tolerations: []
affinity: {}

El proximo paso es revisar la carpeta templates:

deployment.yaml  <--- Recurso deployment estandar de kubernetes con variables de go templates.
_helpers.tpl     <--- En este archivo se definen funciones y variables comunes.
ingress.yaml     <--- Recurso ingress.
NOTES.txt        <--- Este archivo se usa para mostrar las notas una vez que termino el despliegue del chart.
service.yaml     <--- Recurso service de kubernetes o balanceador de carga virtual interno.

Go templates basico, si necesitas refrescar go templates, siempre se puede ir a la documentacion.


Revisemos el archivo [deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/): ```yaml apiVersion: apps/v1beta2 kind: Deployment metadata: name: {{ include "hello-world.fullname" . }} labels: app.kubernetes.io/name: {{ include "hello-world.name" . }} helm.sh/chart: {{ include "hello-world.chart" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app.kubernetes.io/name: {{ include "hello-world.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: labels: app.kubernetes.io/name: {{ include "hello-world.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} spec: containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - name: http containerPort: 80 protocol: TCP livenessProbe: httpGet: path: / port: http readinessProbe: httpGet: path: / port: http resources: {{ toYaml .Values.resources | indent 12 }} {{- with .Values.nodeSelector }} nodeSelector: {{ toYaml . | indent 8 }} {{- end }} {{- with .Values.affinity }} affinity: {{ toYaml . | indent 8 }} {{- end }} {{- with .Values.tolerations }} tolerations: {{ toYaml . | indent 8 }} {{- end }} ``` La mayoria de los campos se reemplazan con lo que pasemos via `values.yaml` esto se pasa via `.Values` a menos que uses un helper o variable extra.

Sigamos con el archivo service:

apiVersion: v1
kind: Service
metadata:
  name: {{ include "hello-world.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "hello-world.name" . }}
    helm.sh/chart: {{ include "hello-world.chart" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: {{ include "hello-world.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}

Luego el archivo [ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/): ```yaml {{- if .Values.ingress.enabled -}} {{- $fullName := include "hello-world.fullname" . -}} {{- $ingressPath := .Values.ingress.path -}} apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ $fullName }} labels: app.kubernetes.io/name: {{ include "hello-world.name" . }} helm.sh/chart: {{ include "hello-world.chart" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- with .Values.ingress.annotations }} annotations: {{ toYaml . | indent 4 }} {{- end }} spec: {{- if .Values.ingress.tls }} tls: {{- range .Values.ingress.tls }} - hosts: {{- range .hosts }} - {{ . | quote }} {{- end }} secretName: {{ .secretName }} {{- end }} {{- end }} rules: {{- range .Values.ingress.hosts }} - host: {{ . | quote }} http: paths: - path: {{ $ingressPath }} backend: serviceName: {{ $fullName }} servicePort: http {{- end }} {{- end }} ``` Este es probablemente el archivo mas interesante por que hace uso de variables locales, tambien itera sobre `hosts`.

Desplegando nuestro chart:

$ helm install --name my-nginx -f values.yaml .
NAME:   my-nginx
LAST DEPLOYED: Sun Dec 23 00:30:11 2018
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Service
NAME                  AGE
my-nginx-hello-world  0s

==> v1beta2/Deployment
my-nginx-hello-world  0s

==> v1/Pod(related)

NAME                                   READY  STATUS   RESTARTS  AGE
my-nginx-hello-world-6f948db8d5-s76zl  0/1    Pending  0         0s

NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=hello-world,app.kubernetes.io/instance=my-nginx" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:80

Nuestro despliegue parece exitoso, ya que vemos el pod con estado Pending inmediatamente.

Revisando el servicio:

$ kubectl get services
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes             ClusterIP   10.96.0.1       <none>        443/TCP   1h
my-nginx-hello-world   ClusterIP   10.111.222.70   <none>        80/TCP    5m

Podemos probar desde otro pod de manera interactiva si todo funciona correctamente: ```nginx $ kubectl run -i --tty alpine --image=alpine -- sh If you don't see a command prompt, try pressing enter.

/ # apk add curl fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz (1/5) Installing ca-certificates (20171114-r3) (2/5) Installing nghttp2-libs (1.32.0-r0) (3/5) Installing libssh2 (1.8.0-r3) (4/5) Installing libcurl (7.61.1-r1) (5/5) Installing curl (7.61.1-r1) Executing busybox-1.28.4-r2.trigger Executing ca-certificates-20171114-r3.trigger OK: 6 MiB in 18 packages

/ # curl -v my-nginx-hello-world

  • Rebuilt URL to: my-nginx-hello-world/
  • Trying 10.111.222.70...
  • TCP_NODELAY set
  • Connected to my-nginx-hello-world (10.111.222.70) port 80 (#0)

GET / HTTP/1.1 Host: my-nginx-hello-world User-Agent: curl/7.61.1 Accept: /

< HTTP/1.1 200 OK < Server: nginx/1.14.2 < Date: Sun, 23 Dec 2018 03:45:31 GMT < Content-Type: text/html < Content-Length: 612 < Last-Modified: Tue, 04 Dec 2018 14:44:49 GMT < Connection: keep-alive < ETag: "5c0692e1-264" < Accept-Ranges: bytes <

Welcome to nginx!

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.

* Connection #0 to host my-nginx-hello-world left intact ``` y voila, como podemos ver nuestro chart de nginx funciona perfectamente.

Podemos verificar el estado via helm de esta manera:

$ helm ls
NAME            REVISION        UPDATED                         STATUS          CHART                   APP VERSION     NAMESPACE
my-nginx        1               Sun Dec 23 00:30:11 2018        DEPLOYED        hello-world-0.1.0       1.0             default

Actualizemos nuestro despliegue cambiando el tag en el archivo values.yaml de stable a mainline y tambien actualizemos la metadata en Chart.yaml para mantener la version de nuestro chart en buenas condiciones.

 $ helm upgrade my-nginx . -f values.yaml
Release "my-nginx" has been upgraded. Happy Helming!
LAST DEPLOYED: Sun Dec 23 00:55:22 2018
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Pod(related)
NAME                                   READY  STATUS             RESTARTS  AGE
my-nginx-hello-world-6f948db8d5-s76zl  1/1    Running            0         25m
my-nginx-hello-world-c5cdcc95c-shgc6   0/1    ContainerCreating  0         0s

==> v1/Service

NAME                  AGE
my-nginx-hello-world  25m

==> v1beta2/Deployment
my-nginx-hello-world  25m


NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=hello-world,app.kubernetes.io/instance=my-nginx" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:80

Parece que todo salio bien, como podemos ver cambio la revision y la version del chart

$ helm ls
NAME            REVISION        UPDATED                         STATUS          CHART                   APP VERSION     NAMESPACE
my-nginx        2               Sun Dec 23 00:55:22 2018        DEPLOYED        hello-world-0.1.1       1.0             default

Ahora verifiquemos que la version de nginx es la que nosotros especificamos:

$ kubectl exec my-nginx-hello-world-c5cdcc95c-shgc6 -- /usr/sbin/nginx -v
nginx version: nginx/1.15.7

al momento de escribir esto la version mainline es 1.15.7, podemos hacer "rollback" si algo no salio bien con helm de esta manera: ```bash $ helm rollback my-nginx 1 Rollback was a success! Happy Helming! ``` Hay varias formas de hacer rollback, en este caso para nuestro chart `my-nginx` especificamos la revision a la que queremos hacer "rollback" y voila.

Revisemos la version de nginx de nuevo:

$ kubectl exec my-nginx-hello-world-6f948db8d5-bsml2 -- /usr/sbin/nginx -v
nginx version: nginx/1.14.2

Siempre es una buena idea limpiar todo cuando terminamos de probar algo:

$ helm del --purge my-nginx
release "my-nginx" deleted

Si necesitas depurar o ver los templates a medida que vas trabajando en ellos podes hacer lo siguiente:

$ helm template . -n name -f values.yaml
# Source: hello-world/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: name-hello-world

Y eso es todo por hoy, ante cualquier duda deja un comentario o revisa la documentacion y el comando helm help.

DRY: Don't Repeat Yourself

Lo bueno de usar templates es que podemos ahorrar mucho tiempo y a la vez mantener todo ordenado y sin mucha repeticion.

Upcoming topics

Algunos articulos que te pueden interesar:


Errata

Si ves algun error por favor enviame un mensaje para poder corregirlo.



$ Comentarios

Online: 0

Por favor inicie sesión para poder escribir comentarios.

2018-12-23 | Gabriel Garrido