Fichero de configuración YAML de Kubernetes

Categoría
Descripción

Una de las formas en que se pueden configurar los objetos de Kubernetes es mediante un fichero YAML (YML). Cada fichero puede contener uno o más manifiestos (en caso de tener varios, cada manifiesto se separa del siguiente mediante ---). Cada uno de estos manifiestos describe un objeto API (deployment, job, secret) y está compuesto necesariamente de las siguientes partes, que conforman sus nodos raíz:

apiVersion:
kind:
metadata:
spec:

Comandos útiles

Antes de meternos en los nodos, vamos a ver ciertos comandos necesarios que nos van a ayudar a cumplimentar la información de los mismos.

Mediante el comando kubectl api-resources podemos obtener el listado de recursos soportados por el cluster. Se obtiene un listado como el siguiente (muestro un listado parcial para claridad de la explicación):

NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND
bindings                                                                      true         Binding
componentstatuses                 cs                                          false        ComponentStatus
configmaps                        cm                                          true         ConfigMap
endpoints                         ep                                          true         Endpoints
events                            ev                                          true         Event
limitranges                       limits                                      true         LimitRange
namespaces                        ns                                          false        Namespace
nodes                             no                                          false        Node
persistentvolumeclaims            pvc                                         true         PersistentVolumeClaim
persistentvolumes                 pv                                          false        PersistentVolume
pods                              po                                          true         Pod
podtemplates                                                                  true         PodTemplate
replicationcontrollers            rc                                          true         ReplicationController
resourcequotas                    quota                                       true         ResourceQuota
secrets                                                                       true         Secret
serviceaccounts                   sa                                          true         ServiceAccount
services                          svc                                         true         Service
mutatingwebhookconfigurations                  admissionregistration.k8s.io   false        MutatingWebhookConfiguration validatingwebhookconfigurations                admissionregistration.k8s.io   false        ValidatingWebhookConfiguration
customresourcedefinitions         crd,crds     apiextensions.k8s.io           false        CustomResourceDefinition
apiservices                                    apiregistration.k8s.io         false        APIService
controllerrevisions                            apps                           true         ControllerRevision
daemonsets                        ds           apps                           true         DaemonSet
deployments                       deploy       apps                           true         Deployment
replicasets                       rs           apps                           true         ReplicaSet
statefulsets                      sts          apps                           true         StatefulSet
tokenreviews                                   authentication.k8s.io          false        TokenReview

.... SIGUE ....

Donde la columna ApiGroup indica el grupo de APIs donde se puede crear/modificar/eliminar el recurso. En ocasiones puede ocurrir que un mismo recurso se encuentre en distintos ApiGroups. Esto se debe a que entre versiones de Kubernetes dicho recurso vaya evolucionando y moviéndose de un grupo a otro, pero manteniéndose temporalmente en el grupo origen por compatibilidad. Siempre que sea posible, se deberá consultar la documentación y comprobar cuál es el ApiGroup más reciente y cuál se va a deprecar.

Mediante el comando kubectl api-versions, se obtienen las versiones de API soportadas por el cluster, mostrando un listado similar al siguiente (elimino parte de las líneas para claridad de la explicación):

admissionregistration.k8s.io/v1
apps/v1
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
events.k8s.io/v1beta1
extensions/v1beta1
networking.k8s.io/v1
networking.k8s.io/v1beta1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1

Se puede ver que hay una relación entre ambos listados: en el caso del recurso replicasets, podemos ver que pertenece al ApiGroup apps. En el segundo listado, podemos ver que hay una única versión de apps, que es apps/v1. Si nos fijamos en el api authentication, veremos que hay 2 versiones: authentication.k8s.io/v1 y
authentication.k8s.io/v1beta1. Si usásemos un recurso cuyo ApiGroup sea authentication, deberemos escoger preferentemente la versión estable del API.

Mediante el comando kubectl explain <recurso> --recursive se obtiene un listado de las diferentes opciones de configuración del recurso <recurso>. Por ejemplo (elimino parte de las lineas para claridad de la explicación):

kubectl explain services --recursive

KIND:     Service
VERSION:  v1

DESCRIPTION:
     Service is a named abstraction of software service (for example, mysql)
     consisting of local port (for example 3306) that the proxy listens on, and
     the selector that determines which pods will answer requests sent through
     the proxy.

FIELDS:
   apiVersion   <string>
   kind <string>
   metadata     <Object>
      annotations       <map[string]string>
      clusterName       <string>
      labels    <map[string]string>
      managedFields     <[]Object>
         apiVersion     <string>
         time   <string>
      name      <string>
      ownerReferences   <[]Object>
         uid    <string>
      resourceVersion   <string>
   spec <Object>
      clusterIP <string>
      loadBalancerSourceRanges  <[]string>
      ports     <[]Object>
         appProtocol    <string>
         targetPort     <string>
      publishNotReadyAddresses  <boolean>
      type      <string>
   status       <Object>
      loadBalancer      <Object>
         ingress        <[]Object>
            hostname    <string>
            ip  <string>

Si usamos la sintaxis kubectl explain <recurso>.spec, obtendremos una explicación detallada de las opciones que se deben configurar en la sección spec. Por ejemplo (incluyo las primeras líneas para claridad de la explicación):

kubectl explain services.spec

KIND:     Service
VERSION:  v1

RESOURCE: spec <Object>

DESCRIPTION:
     Spec defines the behavior of a service.
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

     ServiceSpec describes the attributes that a user creates on a service.

FIELDS:
   clusterIP    <string>
     clusterIP is the IP address of the service and is usually assigned randomly
     by the master. If an address is specified manually and is not in use by
     others, it will be allocated to the service; otherwise, creation of the
     service will fail. This field can not be changed through updates. Valid
     values are "None", empty string (""), or a valid IP address. "None" can be
     specified for headless services when proxying is not required. Only applies
     to types ClusterIP, NodePort, and LoadBalancer. Ignored if type is
     ExternalName. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies

   externalIPs  <[]string>
     externalIPs is a list of IP addresses for which nodes in the cluster will
     also accept traffic for this service. These IPs are not managed by
     Kubernetes. The user is responsible for ensuring that traffic arrives at a
     node with this IP. A common example is external load-balancers that are not
     part of the Kubernetes system.

   externalName <string>
     externalName is the external reference that kubedns or equivalent will
     return as a CNAME record for this service. No proxying will be involved.

.... SIGUE ....

Para obtener información de un campo concreto, usamos la sintaxis kubectl explain <recurso>.spec.<campo>, que mostrará la explicación detallada de <campo>. Por ejemplo:

kubectl explain services.spec.type

KIND:     Service
VERSION:  v1

FIELD:    type <string>

DESCRIPTION:
     type determines how the Service is exposed. Defaults to ClusterIP. Valid
     options are ExternalName, ClusterIP, NodePort, and LoadBalancer.
     "ExternalName" maps to the specified externalName. "ClusterIP" allocates a
     cluster-internal IP address for load-balancing to endpoints. Endpoints are
     determined by the selector or if that is not specified, by manual
     construction of an Endpoints object. If clusterIP is "None", no virtual IP
     is allocated and the endpoints are published as a set of endpoints rather
     than a stable IP. "NodePort" builds on ClusterIP and allocates a port on
     every node which routes to the clusterIP. "LoadBalancer" builds on NodePort
     and creates an external load-balancer (if supported in the current cloud)
     which routes to the clusterIP. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types

Se pueden seguir concatenando la sintaxis .campo para poder acceder a la información de los sub-campos para un campo. Por ejemplo: kubectl explain deployment.spec.template.spec.volumes nos mostrará la información de volumes, que depende del spec propio de template, que a su vez pertenece al spec de deployment. Esto en el YAML quedaría de la siguiente forma:

spec:
  template:
    spec:
      volumes:

Nodos

Una vez vistos estos comandos, podemos entender la información a rellenar en cada nodo:

  • apiVersion: versión del API (listado de kubectl api-versions) que queremos utilizar para el recurso. Por ejemplo, si queremos crear un deployment, deberemos escoger apps/v1.
  • kind: deberemos escoger el texto correspondiente a la columna kind (del listado de kubectl api-resources) del tipo de objeto que deseemos crear. Por ejemplo, para crear un pod usaremos Pod. Para crear un replicaset usaremos la palabra ReplicaSet.
  • metadata: contiene los nodos:
    • name: (requerido) indica el nombre del objeto
    • labels: admite una lista de pares clave:valor que contienen información no necesariamente estándar pero útil para los desarrolladores/arquitectos/gestores. Por ejemplo, información sobre el entorno (env:prod), situación (location:dmz), tipo de aplicación (app:apiclient), nombre del cliente (customer:EmpresaSL).... 
      • Esta información puede usarse posteriormente para filtrar objetos al utilizar los comandos kubectl get. Por ejemplo: kubectl get pods -l env=prod listaría todos los pods cuya etiqueta env tenga el valor prod.
      • También se utiliza en los selectores de etiqueta de los objetos cuando sea necesario dirigirse a un pod concreto
  • spec: contiene todos los nodos de configuración del objeto. Se debe utilizar la información obtenida mediante los comandos kubectl explain explicados anteriormente.