El autor seleccionó Open Internet/Free Speech para recibir una donación como parte del programa Write for DOnations.
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.
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:
...
apiVersion: v1
kind: Service
Nombre el servicio como php
, ya que proporcionará acceso a PHP-FPM:
...
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
.
...
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
.
...
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
:
...
ports:
- protocol: TCP
port: 9000
Su archivo php_service.yaml
completo tendrá el siguiente aspecto:
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:
Outputservice/php created
Verifique que su servicio esté en ejecución:
- kubectl get svc
Observará su servicio de PHP-FPM en ejecución:
OutputNAME 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:
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.
...
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:
...
spec:
externalIPs:
- your_public_ip
Su archivo nginx_service.yaml
tendrá este aspecto:
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:
Outputservice/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:
OutputNAME 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.
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.
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
:
...
stringData:
access-token: your-api-token
Guarde y cierre el archivo.
Su archivo secret.yaml
tendrá el siguiente aspecto:
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:
Outputsecret/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:
OutputNAME 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:
Outputstorageclass.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.
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:
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.
...
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.
...
storageClassName: do-block-storage
Su archivo code_volume.yaml
tendrá el siguiente aspecto:
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.
Outputpersistentvolumeclaim/code created
Para visualizar volúmenes persistentes (VP) disponibles:
- kubectl get pv
Verá su VP enumerado:
OutputNAME 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.
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:
<?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
:
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:
...
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:
...
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
:
...
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:
...
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:
...
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:
...
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 coma
ndo. 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
:
...
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
:
...
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:
...
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:
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:
Outputdeployment.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:
OutputNAME 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:
OutputNAME 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
:
OutputNAME 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
.
OutputNAME 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:
- kubectl describe pods pod-name
- kubectl logs pod-name
- 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.
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
:
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
:
...
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:
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:
Outputconfigmap/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
:
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:
...
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:
...
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:
...
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:
...
- 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:
...
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
:
...
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:
...
- name: config
mountPath: /etc/nginx/conf.d
Su archivo nginx_deployment.yaml
tendrá el siguiente aspecto:
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:
Outputdeployment.apps/nginx created
Enumere sus implementaciones con el siguiente comando:
- kubectl get deployments
Visualizará las implementaciones de Nginx y PHP-FPM:
OutputNAME 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:
OutputNAME 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:
OutputNAME 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.
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.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.