El autor seleccionó Open Internet/Free Speech para recibir una donación como parte del programa Write for DOnations.

Introducción

Kubernetes es un sistema de orquestación de contenedores de código abierto. Le permite crear, actualizar y escalar contenedores sin preocuparse por el tiempo de inactividad.

Para ejecutar una aplicación PHP, Nginx funciona como proxy para PHP-FPM. Disponer esta configuración en un solo contenedor puede ser un proceso engorroso, pero Kubernetes permitirá administrar ambos servicios en contenedores separados. Utilizar Kubernetes le permitirá lograr que sus contenedores sean reutilizables e intercambiables, y no tendrá que reconstruir la imagen de sus contenedores cada vez que haya una nueva versión de Nginx o PHP.

En este tutorial, implementará una aplicación PHP 7 en un clúster de Kubernetes con Nginx y PHP-FPM ejecutándose en contenedores separados. También aprenderá a mantener los archivos de configuración y el código de aplicación fuera de la imagen de contenedor que utilice el sistema de almacenamiento en bloque de DigitalOcean. Este enfoque le permitirá reutilizar la imagen de Nginx para cualquier aplicación que necesite un servidor web o proxy pasando un volumen de configuración en lugar de reconstruir la imagen.

Requisitos previos

Paso 1: Crear los servicios de PHP-FPM y Nginx

En este paso, creará los servicios de PHP-FPM y Nginx. Un servicio permite acceder a un conjunto de pods desde el interior del clúster. Los servicios dentro de un clúster pueden comunicarse de forma directa a través de sus nombres, sin necesidad de direcciones IP. El servicio de PHP-FPM permitirá el acceso a los pods de PHP-FPM, mientras que el servicio Nginx permitirá el acceso a los pods de Nginx.

Debido a que los pods de Nginx representarán los pods de PHP-FPM, tendrá que indicar al servicio la forma de encontrarlos. En lugar de utilizar direcciones IP, aprovechará la detección automática de servicios de Kubernetes para utilizar nombres legibles para humanos para dirigir solicitudes al servicio apropiado.

Para crear el servicio, creará un archivo de definición de objeto. Cada definición de objeto de Kubernetes es un archivo YAML que contiene por lo menos los siguientes elementos:

  • apiVersion: versión de la API de Kubernetes a la que pertenece la definición.
  • kind: objeto de Kubernetes que este archivo representa. Por ejemplo,un pod o service.
  • metadata: contiene el name del objeto junto con cualquier labels que desee aplicarle.
  • spec: contiene una configuración específica según el tipo de objeto que cree, como la imagen del contenedor o los puertos en los cuales se podrá acceder a este.

Primero, creará un directorio para contener sus definiciones de objetos de Kubernetes.

Aplique SSH a su *nodo maestro *y cree el directorio definitions que contendrá sus definiciones de objetos de Kubernetes.

  • mkdir definitions

Acceda al directorio definitions recién creado:

  • cd definitions

Realice su servicio de PHP-FPM creando un archivo php_service.yaml:

  • nano php_service.yaml

Establezca kind como Service para especificar que este objeto es un servicio:

php_service.yaml
...
apiVersion: v1
kind: Service

Nombre el servicio como php, ya que proporcionará acceso a PHP-FPM:

php_service.yaml
...
metadata:
  name: php

Agrupará de manera lógica diferentes objetos con etiquetas. En este tutorial, utilizará etiquetas para agrupar los objetos en “niveles”, como frontend o backend. Los pods de PHP se ejecutarán detrás de este servicio, por lo que le asignará la etiqueta tier: backend.

php_service.yaml
...
  labels:
    tier: backend

Un servicio determina los pods a los que se debe acceder utilizando las etiquetas selector. Se servirá un pod que coincida con estas etiquetas, independiente de que este se cree antes o después del servicio. Agregará etiquetas para sus pods posteriormente en el tutorial.

Utilice la etiqueta tier: backend para asignar el pod al nivel de backend. También agregará la etiqueta app: php para especificar que este pod ejecuta PHP. Agregue estas dos etiquetas después de la sección de metadata.

php_service.yaml
...
spec:
  selector:
    app: php
    tier: backend

A continuación, especifique el puerto utilizado para acceder a este servicio. En este tutorial, utilizará el puerto 9000. Añádalo al archivo php_service.yaml en spec:

php_service.yaml
...
  ports:
    - protocol: TCP
      port: 9000

Su archivo php_service.yaml completo tendrá el siguiente aspecto:

php_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: php
  labels:
    tier: backend
spec:
  selector:
    app: php
    tier: backend
  ports:
  - protocol: TCP
    port: 9000

Presione CTRL + o para guardar el archivo y luego CTRL + x para cerrar nano.

Ahora que ha creado la definición de objeto para su servicio, para ejecutar el servicio utilizará el comando kubectl apply junto con el argumento -f y especificará su archivo php_service.yaml.

Cree su servicio:

  • kubectl apply -f php_service.yaml

Este resultado confirma la creación del servicio:

Output
service/php created

Verifique que su servicio esté en ejecución:

  • kubectl get svc

Observará su servicio de PHP-FPM en ejecución:

Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m php ClusterIP 10.100.59.238 <none> 9000/TCP 5m

Kubernetes admite varios tipos de servicios. Su servicio php utiliza el tipo de servicio predeterminado, clusterIP. Este tipo de servicio asigna una IP interna y permite acceder al servicio sólo desde el interior del clúster.

Ahora que el servicio de PHP-FPM está listo, creará el servicio de Nginx. Cree y abra un nuevo archivo llamado nginx_service.yaml con el editor:

  • nano nginx_service.yaml

Este servicio se orientará a los pods de Nginx, por lo que lo llamará nginx. También agregará una etiqueta tier: backend, ya que pertenece al nivel de backend:

nginx_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    tier: backend

De modo similar al servicio php, dirija los pods con las etiquetas de selección app: nginx y tier: backend. Permita que sea posible acceder a este servicio en el puerto 80, el puerto HTTP predeterminado.

nginx_service.yaml
...
spec:
  selector:
    app: nginx
    tier: backend
  ports:
  - protocol: TCP
    port: 80

Será posible acceder al servicio de Nginx de forma pública en Internet desde la dirección IP pública de su Droplet. Puede encontrar your_public_ip desde su panel en la nube de DigitalOcean. En spec.externalIPs, agregue lo siguiente:

nginx_service.yaml
...
spec:
  externalIPs:
  - your_public_ip

Su archivo nginx_service.yaml tendrá este aspecto:

nginx_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    tier: backend
spec:
  selector:
    app: nginx
    tier: backend
  ports:
  - protocol: TCP
    port: 80
  externalIPs:
  - your_public_ip    

Guarde y cierre el archivo. Cree el servicio de Nginx:

  • kubectl apply -f nginx_service.yaml

Observará el siguiente resultado cuando el servicio esté en ejecución:

Output
service/nginx created

Puede ver todos los servicios en funcionamiento ejecutando lo siguiente:

  • kubectl get svc

Observará los servicios de PHP-FPM y Nginx enumerados en el resultado:

Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13m nginx ClusterIP 10.102.160.47 your_public_ip 80/TCP 50s php ClusterIP 10.100.59.238 <none> 9000/TCP 8m

Tenga en cuenta que si desea eliminar un servicio puede ejecutar lo siguiente:

  • kubectl delete svc/service_name

Ahora que creó sus servicios de PHP-FPM y Nginx, deberá especificar el lugar de almacenamiento para el código de su aplicación y sus archivos de configuración.

Paso 2: Instalar el complemento de almacenamiento de DigitalOcean

Kubernetes proporciona diversos complementos de almacenamiento que pueden crear el espacio de almacenamiento para su entorno. En este paso, instalará el complemento de almacenamiento de DigitalOcean para crear un almacén en bloques en DigitalOcean. Una vez completada la instalación, agregará una clase de almacenamiento llamada do-block-storage que utilizará para crear su almacenamiento en bloques.

Primero configurará un objeto secreto de Kubernetes para almacenar su token de API de DigitalOcean. Los objetos secretos se utilizan para compartir información confidencial, como claves y contraseñas SSH, con otros objetos de Kubernetes dentro del mismo espacio de nombres. Los espacios de nombres ofrecen una alternativa lógica para separar sus objetos de Kubernetes.

Abra un archivo llamado secret.yaml con el editor:

  • nano secret.yaml

Nombre su objeto secreto digitalocean y agréguelo al namespace kube-system. kube-system es el espacio de nombres predeterminado para los servicios internos de Kubernetes y el complemento de almacenamiento de DigitalOcean también lo utiliza para iniciar varios componentes.

secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: digitalocean
  namespace: kube-system

En lugar de una clave spec, un secreto utiliza una clave data o stringData para contener la información necesaria. El parámetro data contiene datos codificados en base64 que se decodifican de manera automática cuando se recuperan. El parámetro stringData contiene datos no codificados que se codifican de manera automática durante la creación o actualización, y no muestra los datos al recuperar secretos. En este tutorial, utilizará stringData para una mayor practicidad.

Agregue el access-token como stringData:

secret.yaml
...
stringData:
  access-token: your-api-token

Guarde y cierre el archivo.

Su archivo secret.yaml tendrá el siguiente aspecto:

secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: digitalocean
  namespace: kube-system
stringData:
  access-token: your-api-token

Cree el secreto:

  • kubectl apply -f secret.yaml

Verá este resultado al crear secretos:

Output
secret/digitalocean created

Puede visualizar el secreto con el siguiente comando:

  • kubectl -n kube-system get secret digitalocean

El resultado tendrá un aspecto similar a este:

Output
NAME TYPE DATA AGE digitalocean Opaque 1 41s

El tipo Opaque implica que este secreto es de sólo lectura, parámetro estándar para los secretos de stringData. Puede obtener más información más acerca de ello en las especificaciones de diseño de secretos. El campo DATA muestra el número de elementos almacenados en este secreto. En este caso, muestra 1 porque tiene una sola clave almacenada.

Ahora que su secreto está implementado, instale el complemento de almacenamiento en bloques de DigitalOcean:

  • kubectl apply -f https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v0.3.0.yaml

Verá resultados similares al siguiente:

Output
storageclass.storage.k8s.io/do-block-storage created serviceaccount/csi-attacher created clusterrole.rbac.authorization.k8s.io/external-attacher-runner created clusterrolebinding.rbac.authorization.k8s.io/csi-attacher-role created service/csi-attacher-doplug-in created statefulset.apps/csi-attacher-doplug-in created serviceaccount/csi-provisioner created clusterrole.rbac.authorization.k8s.io/external-provisioner-runner created clusterrolebinding.rbac.authorization.k8s.io/csi-provisioner-role created service/csi-provisioner-doplug-in created statefulset.apps/csi-provisioner-doplug-in created serviceaccount/csi-doplug-in created clusterrole.rbac.authorization.k8s.io/csi-doplug-in created clusterrolebinding.rbac.authorization.k8s.io/csi-doplug-in created daemonset.apps/csi-doplug-in created

Ahora que instaló el complemento de almacenamiento de DigitalOcean, puede crear almacenamiento en bloques para contener el código de su aplicación y sus archivos de configuración.

Paso 3: Crear el volumen persistente

Con su secreto implementado y el complemento de almacenamiento en bloques instalado, estará listo para crear su volumen persistente. Un volumen persistente, o VP, es un almacenamiento en bloques de un tamaño especifico que es independiente del ciclo de vida de un pod. Utilizar un volumen persistente le permitirá administrar o actualizar sus pods sin preocuparse por la posibilidad de perder el código de su aplicación. El acceso a un volumen persistente es posible utilizando un PersistentVolumeClaim, o PVC, que monta el VP en la ruta requerida.

Abra un archivo llamado code_volume.yaml con su editor:

  • nano code_volume.yaml

Dé el nombre code al PVC agregando los siguientes parámetros y valores a su archivo:

code_volume.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: code

La spec para un PVC contiene los siguientes elementos:

  • accessModes que varían según el caso de uso. Son los siguientes:
    • ReadWriteOnce: monta el volumen con atributos de lectura y escritura para un solo nodo.
    • ReadOnlyMany: monta el volumen con atributos de sólo lectura para muchos nodos.
    • ReadWriteMany: monta el volumen con atributos de lectura y escritura para muchos nodos.
  • resources: espacio de almacenamiento que usted requiere.

El almacenamiento en bloques de DigitalOcean solo se monta en un único nodo, por lo que usted fijará accessModes en ReadWriteOnce. Este tutorial le servirá de guía para agregar una pequeña cantidad de código de aplicación. Por lo tanto 1 gigabyte será suficiente en este caso de uso. Si planea almacenar una mayor cantidad de código o datos en el volumen, puede modificar el parámetro storage para que se adapte a sus necesidades. Puede aumentar la cantidad de almacenamiento después de crear el volumen, pero no es posible reducir el disco.

code_volume.yaml
...
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

A continuación, especifique la clase de almacenamiento que Kubernetes utilizará para proporcionar los volúmenes. Utilizará la clase do-block-storage creada por el complemento de almacenamiento en bloques de DigitalOcean.

code_volume.yaml
...
  storageClassName: do-block-storage

Su archivo code_volume.yaml tendrá el siguiente aspecto:

code_volume.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: code
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: do-block-storage

Guarde y cierre el archivo.

Cree el elemento code PersistentVolumeClaim utilizando kubectl:

  • kubectl apply -f code_volume.yaml

El siguiente resultado le indica que el objeto se creó de forma correcta y está listo para montar su PVC de 1 GB como un volumen.

Output
persistentvolumeclaim/code created

Para visualizar volúmenes persistentes (VP) disponibles:

  • kubectl get pv

Verá su VP enumerado:

Output
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-ca4df10f-ab8c-11e8-b89d-12331aa95b13 1Gi RWO Delete Bound default/code do-block-storage 2m

A excepción de Reclaim Policy y Status, en los campos anteriores se muestra un resumen de su archivo de configuración. Reclaim Policy define lo que se hace con el VP después de que el PVC que lo accede es eliminado. Delete elimina el VP de Kubernetes y la infraestructura de DigitalOcean. Puede obtener más información sobre Reclaim Policy y Status en la documentación de VP de Kubernetes.

De esta manera, habrá creado correctamente un volumen persistente utilizando el complemento de almacenamiento en bloques de DigitalOcean. Ahora que su volumen persistente está listo, creará sus pods con una implementación.

Paso 4: Crear una implementación de PHP-FPM

En este paso, aprenderá a utilizar una implementación para crear su pod de PHP-FPM. Las implementaciones proporcionan una manera uniforme de crear, actualizar y administrar pods utilizando ReplicaSets. Si una actualización no funciona como se espera, una implementación restaurará de manera automática sus pods a una imagen anterior.

La clave de despliegue spec.selector enumerará las etiquetas de los pods que administrará. También utilizará la clave template para crear los pods necesarios.

En este paso también se introducirá el uso de contenedores Init. Los contenedores Init ejecutan uno o más comandos antes que los contenedores regulares especificados en la clave template del pod. En este tutorial, su contenedor Init obtendrá un archivo de muestra de index.php de GitHub Gist utilizando wget. El archivo de muestra contiene lo siguiente:

index.php
<?php
echo phpinfo();

Para crear su implementación, abra un nuevo archivo llamado php_deployment.yaml con su editor:

  • nano php_deployment.yaml

Esta implementación administrará sus pods de PHP-FPM, por lo que dará al objeto de implementación el nombre php. Los pods pertenecen al nivel de backend, por lo que agrupará la implementación en este grupo utilizando la etiqueta tier: backend:

php_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php
  labels:
    tier: backend

Para la implementación spec, especificará la cantidad de copias de este pod que se crearán utilizando el parámetro replicas. El número de replicas variará según sus necesidades y los recursos disponibles. En este tutorial, creará una réplica:

php_deployment.yaml
...
spec:
  replicas: 1

La implementación administrará pods que coincidan con app: php y las etiquetas de tier: backend. En la clave de selector agregue:

php_deployment.yaml
...
  selector:
    matchLabels:
      app: php
      tier: backend

A continuación, la implementación spec requiere el elemento template para la definición de objeto de su pod. Esta plantilla definirá las especificaciones a partir de las cuales se creará el pod. Primero, agregará las etiquetas que se especificaron para el servicio php selectors y las matchLabels de la implementación. Agregue app: php y tier: backend en template.metadata.labels:

php_deployment.yaml
...
  template:
    metadata:
      labels:
        app: php
        tier: backend

Un pod puede tener varios contenedores y volúmenes, pero cada uno requerirá un nombre. Puede montar de manera selectiva volúmenes en un contenedor especificando una ruta de montaje para cada volumen.

Primero, especifique los volúmenes a los que accederá su contenedor. Creó un PVC llamado code para contener el código de su aplicación. Por lo tanto dé el nombre code a este volumen también. En spec.template.spec.volumes, agregue lo siguiente:

php_deployment.yaml
...
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code

A continuación, especifique el contenedor que desee ejecutar en este pod. Puede encontrar varias imágenes en la tienda de Docker, pero en este tutorial empleará la imagen php:7-fpm.

En spec.template.spec.containers, agregue lo siguiente:

php_deployment.yaml
...
      containers:
      - name: php
        image: php:7-fpm

A continuación, montará los volúmenes a los que el contenedor solicita acceso. Este contenedor ejecutará su código PHP, de modo que deberá acceder al volumen code. También utilizará mountPath para especificar /code como punto de montaje.

En spec.template.spec.containers.volumeMounts, agregue lo siguiente:

php_deployment.yaml
...
        volumeMounts:
        - name: code
          mountPath: /code

Ahora que montó su volumen, debe introducir el código de su aplicación en el volumen. Es posible que para hacerlo haya utilizado previamente FTP/SFTP o clonado el código a través de una conexión SSH, pero en este paso verá la forma de copiar el código utilizando un contenedor Init.

Según la complejidad de su proceso de configuración, puede utilizar un solo initContainer para ejecutar una secuencia de comandos que construya su aplicación, o puede utilizar un initContainer por comando. Asegúrese de que los volúmenes se monten en el initContainer.

En este tutorial, utilizará un contenedor Init único con busybox para descargar el código. busybox es una pequeña imagen que contiene la utilidad wget que utilizará para hacerlo.

En spec.template.spec, agregue su initContainer y especifique la imagen busybox:

php_deployment.yaml
...
      initContainers:
      - name: install
        image: busybox

Su contenedor Init necesitará acceso al volumen code para que pueda descargar el código en esa ubicación. En spec.template.spec.initContainers, monte el volumen code en la ruta /code:

php_deployment.yaml
...
        volumeMounts:
        - name: code
          mountPath: /code

Cada contenedor Init debe ejecutar un command. Su contenedor Init utilizará wget para descargar el código de Github en el directorio de trabajo /code. La opción -O asigna un nombre al archivo descargado, y usted dará a este archivo el nombre index.php.

Nota: Asegúrese de el código que extraerá sea confiable. Antes de introducir el código fuente en su servidor, inspecciónelo para asegurarse de que las funciones que realiza le parezcan adecuadas.

En el contenedor install en spec.template.spec.initContainers, agregue estas líneas:

php_deployment.yaml
...
        command:
        - wget
        - "-O"
        - "/code/index.php"
        - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php

Su archivo php_deployment.yaml completo tendrá este aspecto:

php_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php
  labels:
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: php
      tier: backend
  template:
    metadata:
      labels:
        app: php
        tier: backend
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code
      containers:
      - name: php
        image: php:7-fpm
        volumeMounts:
        - name: code
          mountPath: /code
      initContainers:
      - name: install
        image: busybox
        volumeMounts:
        - name: code
          mountPath: /code
        command:
        - wget
        - "-O"
        - "/code/index.php"
        - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php

Guarde el archivo y salga del editor.

Cree la implementación de PHP-FPM con kubectl:

  • kubectl apply -f php_deployment.yaml

Visualizará el siguiente resultado al crear la implementación:

Output
deployment.apps/php created

A modo de resumen, esta implementación se iniciará descargando las imágenes especificadas. Luego, solicitará el PersistentVolume de su PersistentVolumeClaim y ejecutará en serie sus initContainers. Una vez completado el proceso, los contenedores ejecutarán y montarán los volumes en punto de montaje especificado. Una vez que todos estos pasos se hayan completado, su pod estará listo y en ejecución.

Puede ver su implementación ejecutando lo siguiente:

  • kubectl get deployments

Verá el siguiente resultado:

Output
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE php 1 1 1 0 19s

Este resultado puede ayudarle a comprender el estado actual de la implementación. Deployment es uno de los controladores que conservan un estado deseado. El elemento template que creó especifica que un elemento replicas del pod del estado DESIRED se llamará php. El campo CURRENT indica cuántas réplicas se encuentran en ejecución, por lo que debe coincidir con el estado DESIRED. Puede leer información sobre los campos restantes en la documentación de implementación de Kubernetes.

Puede ver los pods iniciados por esta implementación con el siguiente comando:

  • kubectl get pods

El resultado de este comando varía según el tiempo transcurrido desde la creación de la implementación. Si la ejecuta poco después de su creación, el resultado probablemente tendrá este aspecto:

Output
NAME READY STATUS RESTARTS AGE php-86d59fd666-bf8zd 0/1 Init:0/1 0 9s

Las columnas representan la siguiente información:

  • Ready: número de replicas que ejecutan este pod.
  • Status: estado del pod. Init indica que los contenedores Init están en ejecución. En este resultado, del total de 1 contenedor Init, ninguno terminó de ejecutarse.
  • Restarts: cantidad de veces que este proceso se reinició para iniciar el pod. Este número aumentará si alguno de sus contenedores Init falla. La implementación se reiniciará hasta que alcance un estado deseado.

Según de la complejidad de sus secuencias de comandos de inicio, pueden pasar algunos minutos hasta que el estado cambie a podInitializing:

Output
NAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 0/1 podInitializing 0 39s

Esto significa que los contenedores Init han finalizado y que se están iniciando los contenedores. Si ejecuta el comando cuando todos los contenedores estén en ejecución, verá que el estado de pod cambiará a Running.

Output
NAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 1/1 Running 0 1m

Ahora verá que su pod se ejecuta de forma correcta. Si su pod no se inicia, puede realizar una depuración con los siguientes comandos:

  • Ver información detallada de un pod:
  • kubectl describe pods pod-name
  • Ver registros generados por un pod:
  • kubectl logs pod-name
  • Ver registros para un contenedor específico en un pod:
  • kubectl logs pod-name container-name

Su código de aplicación está montado y el servicio de PHP-FPM ya está listo para manejar conexiones. Ahora podrá crear su implementación de Nginx.

Paso 5: Crear la implementación de Nginx

En este paso, utilizará un ConfigMap para configurar Nginx. Un ConfigMap contiene su configuración en un formato de clave-valor al que puede hacer referencia en otras definiciones de objetos de Kubernetes. Este enfoque le brindará la flexibilidad necesaria para reutilizar o cambiar la imagen con una versión de Nginx distinta si es necesario. Actualizar ConfigMap replicará los cambios de manera automática en cualquier pod montado en él.

Con su editor, cree un archivo nginx_configMap.yaml para su ConfigMap:

  • nano nginx_configMap.yaml

Dé el nombre nginx-config a ConfigMap y agrúpelo en el microservicio de tier: backend:

nginx_configMap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  labels:
    tier: backend

A continuación, agregará data para ConfigMap. Dé a la clave el nombre config y añada el contenido de su archivo de configuración de Nginx como valor. Puede utilizar el ejemplo de configuración de Nginx de este tutorial.

Debido a que Kubernetes puede dirigir solicitudes al host adecuado para un servicio, puede ingresar el nombre de su servicio de PHP-FPM en el parámetro fastcgi_pass en lugar de su dirección IP. Agregue lo siguiente a su archivo nginx_configMap.yaml:

nginx_configMap.yaml
...
data:
  config : |
    server {
      index index.php index.html;
      error_log  /var/log/nginx/error.log;
      access_log /var/log/nginx/access.log;
      root ^/code^;

      location / {
          try_files $uri $uri/ /index.php?$query_string;
      }

      location ~ \.php$ {
          try_files $uri =404;
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass php:9000;
          fastcgi_index index.php;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }

Su archivo nginx_configMap.yaml tendrá el siguiente aspecto:

nginx_configMap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  labels:
    tier: backend
data:
  config : |
    server {
      index index.php index.html;
      error_log  /var/log/nginx/error.log;
      access_log /var/log/nginx/access.log;
      root /code;

      location / {
          try_files $uri $uri/ /index.php?$query_string;
      }

      location ~ \.php$ {
          try_files $uri =404;
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass php:9000;
          fastcgi_index index.php;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }

Guarde el archivo y salga del editor.

Cree el ConfigMap:

  • kubectl apply -f nginx_configMap.yaml

Verá lo siguiente:

Output
configmap/nginx-config created

Con esto, habrá terminado de crear su ConfigMap y ya podrá crear su implementación de Nginx.

Comience abriendo un nuevo archivo nginx_deployment.yaml en el editor:

  • nano nginx_deployment.yaml

Dé el nombre nginx a la implementación y añada la etiqueta tier: backend:

nginx_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    tier: backend

Especifique que desea un elemento replicas en la implementación spec. Esta implementación administra pods con etiquetas app: nginx y tier: backend. Agregue los siguientes parámetros y valores:

nginx_deployment.yaml
...
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      tier: backend

A continuación, agregue el elemento template del pod. Debe utilizar las mismas etiquetas que agregó para selector.matchLabels de la implementación. Agregue lo siguiente:

nginx_deployment.yaml
...
  template:
    metadata:
      labels:
        app: nginx
        tier: backend

Habilite el acceso de Nginx al PVC code que creó previamente. En spec.template.spec.volumes, agregue lo siguiente:

nginx_deployment.yaml
...
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code

Los pods pueden montar un ConfigMap como un volumen. Especificar un nombre de archivo y una clave creará un archivo con su valor como el contenido. Para usar ConfigMap, fije path en el nombre del archivo que tendrá el contenido de key. EL objetivo es crear un archivo site.conf a partir de la clave config. En spec.template.spec.volumes, agregue lo siguiente:

nginx_deployment.yaml
...
      - name: config
        configMap:
          name: nginx-config
          items:
          - key: config
            path: site.conf

Advertencia: Si no se especifica un archivo, el contenido de key sustituirá el elemento mountPath del volumen. Esto quiere decir que si una ruta no está especificada de manera explícita, perderá todo el contenido de la carpeta de destino.

A continuación, especificará la imagen a partir de la cual se creará su pod. En este tutorial se utilizará la imagen nginx:1.7.9 por cuestiones de estabilidad, pero puede encontrar otras imágenes de Nginx en la tienda de Docker. Además, debe hacer que Nginx esté disponible en el puerto 80. En spec.template.spec, agregue lo siguiente:

nginx_deployment.yaml
...
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

Nginx y PHP-FPM deben acceder al archivo en la misma ruta. Por ello, monte el volumen de code en /code:

nginx_deployment.yaml
...
        volumeMounts:
        - name: code
          mountPath: /code

La imagen nginx:1.7.9 cargará de manera automática cualquier archivo de configuración en el directorio /etc/nginx/conf.d. Si se monta el volumen de config en este directorio, se creará el archivo /etc/nginx/conf.d/site.conf. En volumeMounts, agregue lo siguiente:

nginx_deployment.yaml
...
        - name: config
          mountPath: /etc/nginx/conf.d

Su archivo nginx_deployment.yaml tendrá el siguiente aspecto:

nginx_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      tier: backend
  template:
    metadata:
      labels:
        app: nginx
        tier: backend
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code
      - name: config
        configMap:
          name: nginx-config
          items:
          - key: config
            path: site.conf
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
        volumeMounts:
        - name: code
          mountPath: /code
        - name: config
          mountPath: /etc/nginx/conf.d

Guarde el archivo y salga del editor.

Cree la implementación de Nginx:

  • kubectl apply -f nginx_deployment.yaml

El siguiente resultado indica que se creó su implementación:

Output
deployment.apps/nginx created

Enumere sus implementaciones con el siguiente comando:

  • kubectl get deployments

Visualizará las implementaciones de Nginx y PHP-FPM:

Output
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 1 1 1 0 16s php 1 1 1 1 7m

Enumere los pods administrados por ambas implementaciones:

  • kubectl get pods

Visualizará los pods que estén en ejecución:

Output
NAME READY STATUS RESTARTS AGE nginx-7bf5476b6f-zppml 1/1 Running 0 32s php-86d59fd666-lkwgn 1/1 Running 0 7m

Ahora que todos los objetos de Kubernetes están activos, podrá visitar el servicio de Nginx en su navegador.

Enumere los servicios en ejecución:

  • kubectl get services -o wide

Obtenga la IP externa para su servicio de Nginx:

Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 39m <none> nginx ClusterIP 10.102.160.47 your_public_ip 80/TCP 27m app=nginx,tier=backend php ClusterIP 10.100.59.238 <none> 9000/TCP 34m app=php,tier=backend

En su navegador, visite su servidor escribiendo http://your_public_ip. Verá el resultado de php_info() y habrá confirmado que sus servicios de Kubernetes están configurados y activos.

Conclusión

A través de esta guía , cargó en contenedores los servicios de PHP-FPM y Nginx para poder administrarlos de manera independiente. Este enfoque no solo mejorará la escalabilidad de su proyecto a medida que amplíe sus capacidades, sino también le permitirá utilizar los recursos de manera eficaz. También almacenó el código de su aplicación en un volumen para poder actualizar sus servicios de manera sencilla en el futuro.

0 Comments

Creative Commons License