O autor escolheu a Electronic Frontier Foundation para receber uma doação como parte do programa Write for DOnations.
O Kubernetes é um sistema open source de orquestração de container. Ele permite criar, atualizar e escalar containers sem se preocupar com o tempo de inatividade.
Para executar uma aplicação PHP, o Nginx atua como um proxy para o PHP-FPM. Containerizar essa configuração em um único container pode ser um processo complicado, mas o Kubernetes ajudará a gerenciar os dois serviços em containers separados. O uso do Kubernetes permitirá a você manter seus containers reutilizáveis e substituíveis, e você não precisará reconstruir sua imagem de container toda vez que houver uma nova versão do Nginx ou do PHP.
Neste tutorial, você fará o deploy de uma aplicação PHP 7 em um cluster Kubernetes com o Nginx e o PHP-FPM em execução em containers separados. Você também aprenderá como manter os seus arquivos de configuração e o código da aplicação fora da imagem do container usando o sistema de Block Storage da DigitalOcean. Essa abordagem o permitirá reutilizar a imagem do Nginx para qualquer aplicação que precise de um servidor web/proxy passando um volume de configuração, em vez de reconstruir a imagem.
Neste passo, você criará os serviços PHP-FPM e Nginx. Um serviço permite o acesso a um conjunto de pods de dentro do cluster. Os serviços em um cluster podem se comunicar diretamente por meio de seus nomes, sem a necessidade de endereços IP. O serviço PHP-FPM permitirá acesso aos pods PHP-FPM, enquanto o serviço Nginx permitirá acesso aos pods Nginx.
Como os pods do Nginx farão proxy dos pods do PHP-FPM, você precisará informar ao serviço como encontrá-los. Em vez de usar endereços IP, você aproveitará a descoberta automática de serviços do Kubernetes para usar nomes legíveis por humanos para rotear solicitações para o serviço apropriado.
Para criar o serviço, você criará um arquivo de definição de objeto. Toda definição de objeto Kubernetes é um arquivo YAML que contém pelo menos os seguintes itens:
apiVersion
: A versão da API do Kubernetes à qual a definição pertence.kind
: O objeto Kubernetes que este arquivo representa. Por exemplo, um pod
ou service
.metadata
: Isso contém o nome
do objeto, juntamente com quaisquer labels
que você queira aplicar a ele.spec
: Isso contém uma configuração específica, dependendo do tipo de objeto que você está criando, como a imagem do container ou as portas nas quais o container estará acessível.Primeiro, você criará um diretório para armazenar suas definições de objeto do Kubernetes.
Faça SSH no seu node master e crie o diretório definitions
que conterá as definições do objeto Kubernetes.
- mkdir definitions
Navegue até o diretório definitions
recém-criado:
- cd definitions
Defina seu serviço PHP-FPM criando um arquivo php_service.yaml
:
- nano php_service.yaml
Defina kind
como Service
para especificar que este objeto é um serviço:
apiVersion: v1
kind: Service
Nomeie o serviço como php
, pois ele fornecerá acesso ao PHP-FPM:
...
metadata:
name: php
Você agrupará logicamente diferentes objetos com labels ou etiquetas. Neste tutorial, você usará labels para agrupar os objetos em “camadas”, como front-end ou back-end. Os pods do PHP serão executados por trás desse serviço, então você o etiquetará como tier: backend
.
...
labels:
tier: backend
Um serviço determina quais pods acessar usando labels selector
. Um pod que corresponda a essas labels será atendido, independentemente de o pod ter sido criado antes ou depois do serviço. Você adicionará labels para seus pods posteriormente no tutorial.
Use a label tier: backend
para atribuir o pod à camada de back-end. Você também adicionará o rótulo app: php
para especificar que este pod executa o PHP. Adicione essas duas labels após a seção metadados
.
...
spec:
selector:
app: php
tier: backend
Em seguida, especifique a porta usada para acessar este serviço. Você usará a porta 9000
neste tutorial. Adicione-a ao arquivo php_service.yaml
abaixo de spec
:
...
ports:
- protocol: TCP
port: 9000
O arquivo php_service.yaml
completo será semelhante a este:
apiVersion: v1
kind: Service
metadata:
name: php
labels:
tier: backend
spec:
selector:
app: php
tier: backend
ports:
- protocol: TCP
port: 9000
Pressione CTRL + O
para salvar o arquivo, e depois CTRL + X
para sair do nano
.
Agora que você criou a definição de objeto para o seu serviço, para executar o serviço, você usará o comando kubectl apply
junto com a flag -f
e especificará seu arquivo php_service.yaml
.
Crie seu serviço:
- kubectl apply -f php_service.yaml
Esta saída confirma a criação do serviço:
Outputservice/php created
Verifique se o seu serviço está em execução:
- kubectl get svc
Você verá seu serviço PHP-FPM em execução:
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
Existem vários tipos de serviço que o Kubernetes suporta. Seu serviço php
usa o tipo de serviço padrão, ClusterIP
. Esse tipo de serviço atribui um IP interno e torna o serviço acessível apenas de dentro do cluster.
Agora que o serviço PHP-FPM está pronto, você criará o serviço Nginx. Crie e abra um novo arquivo chamado nginx_service.yaml
com o editor:
- nano nginx_service.yaml
Este serviço terá como alvo os pods do Nginx, então você o chamará de nginx
. Você também adicionará uma label tier: backend
, pois ele pertence à camada de backend:
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
tier: backend
Semelhante ao serviço php
, marque os pods com as labels app: nginx
e tier: backend
. Torne este serviço acessível na porta 80
, a porta HTTP padrão.
...
spec:
selector:
app: nginx
tier: backend
ports:
- protocol: TCP
port: 80
O serviço Nginx estará publicamente acessível na Internet a partir do endereço IP público do seu Droplet. seu_ip_público
pode ser encontrado em seu Painel de Controle da DigitalOcean. Sob spec.externalIPs
, adicione:
...
spec:
externalIPs:
- seu_ip_público
Seu arquivo nginx_service.yaml
será parecido com este:
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
tier: backend
spec:
selector:
app: nginx
tier: backend
ports:
- protocol: TCP
port: 80
externalIPs:
- seu_ip_público
Salve e feche o arquivo. Crie o serviço Nginx:
- kubectl apply -f nginx_service.yaml
Você verá a seguinte saída quando o serviço estiver sendo executado:
Outputservice/nginx created
Você pode visualizar todos os serviços em execução executando:
- kubectl get svc
Você verá os serviços PHP-FPM e Nginx listados na saída:
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 seu_ip_público 80/TCP 50s
php ClusterIP 10.100.59.238 <none> 9000/TCP 8m
Observe que, se você deseja excluir um serviço, você pode executar:
- kubectl delete svc/nome_do_serviço
Agora que você criou seus serviços PHP-FPM e Nginx, precisará especificar onde armazenar o código da aplicação e os arquivos de configuração.
O Kubernetes fornece diferentes plug-ins de armazenamento que podem criar o espaço de armazenamento para o seu ambiente. Neste passo, você instalará o plug-in de Armazenamento da DigitalOcean para criar block storage na DigitalOcean. Quando a instalação estiver concluída, ela adicionará uma classe de armazenamento denominada do-block-storage
que você usará para criar seu armazenamento em blocos ou block storage.
Você primeiro configurará um objeto Kubernetes Secret para armazenar seu token da API da DigitalOcean. Objetos Secret são usados para compartilhar informações confidenciais, como chaves e senhas SSH, com outros objetos do Kubernetes no mesmo namespace. Os namespaces fornecem uma maneira de separar logicamente os objetos do Kubernetes.
Abra um arquivo chamado secret.yaml
com o editor:
- nano secret.yaml
Você nomeará seu objeto Secret como digitalocean
e o adicionará ao namespace kube-system
. O namespace kube-system
é o namespace padrão para os serviços internos do Kubernetes e também é usado pelo plug-in de armazenamento da DigitalOcean para ativar vários componentes.
apiVersion: v1
kind: Secret
metadata:
name: digitalocean
namespace: kube-system
Em vez de uma chave spec
, um Secret usa uma chave data
ou stringData
para armazenar as informações necessárias. O parâmetro data
contém dados codificados em base64 que são decodificados automaticamente quando recuperados. O parâmetro stringData
contém dados não codificados que são codificados automaticamente durante a criação ou atualizações e não mostra os dados ao recuperar Secrets. Você usará stringData
neste tutorial por conveniência.
Adicione access-token
como stringData
:
...
stringData:
access-token: seu_token_de_api
Salve e saia do arquivo.
O seu arquivo secret.yaml
ficará assim:
apiVersion: v1
kind: Secret
metadata:
name: digitalocean
namespace: kube-system
stringData:
access-token: seu_token_de_api
Crie o secret:
- kubectl apply -f secret.yaml
Você verá esta saída na criação do Secret:
Outputsecret/digitalocean created
Você pode ver o Secret com o seguinte comando:
- kubectl -n kube-system get secret digitalocean
A saída será semelhante a esta:
OutputNAME TYPE DATA AGE
digitalocean Opaque 1 41s
O tipo Opaque
significa que esse Secret é somente leitura, o que é padrão para os Secrets stringData
. Você pode ler mais sobre isso em Secret design spec. O campo DATA
mostra o número de itens armazenados neste Secret. Neste caso, mostra 1
porque você tem uma única chave armazenada.
Agora que seu Secret está no lugar, instale o plug-in de armazenamento em bloco da DigitalOcean:
- kubectl apply -f https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v1.1.0.yaml
Você verá uma saída semelhante à seguinte:
Outputcsidriver.storage.k8s.io/dobs.csi.digitalocean.com created
customresourcedefinition.apiextensions.k8s.io/volumesnapshotclasses.snapshot.storage.k8s.io created
customresourcedefinition.apiextensions.k8s.io/volumesnapshotcontents.snapshot.storage.k8s.io created
customresourcedefinition.apiextensions.k8s.io/volumesnapshots.snapshot.storage.k8s.io created
storageclass.storage.k8s.io/do-block-storage created
statefulset.apps/csi-do-controller created
serviceaccount/csi-do-controller-sa created
clusterrole.rbac.authorization.k8s.io/csi-do-provisioner-role created
clusterrolebinding.rbac.authorization.k8s.io/csi-do-provisioner-binding created
clusterrole.rbac.authorization.k8s.io/csi-do-attacher-role created
clusterrolebinding.rbac.authorization.k8s.io/csi-do-attacher-binding created
clusterrole.rbac.authorization.k8s.io/csi-do-snapshotter-role created
clusterrolebinding.rbac.authorization.k8s.io/csi-do-snapshotter-binding created
daemonset.apps/csi-do-node created
serviceaccount/csi-do-node-sa created
clusterrole.rbac.authorization.k8s.io/csi-do-node-driver-registrar-role created
clusterrolebinding.rbac.authorization.k8s.io/csi-do-node-driver-registrar-binding created
error: unable to recognize "https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v1.1.0.yaml": no matches for kind "VolumeSnapshotClass" in version "snapshot.storage.k8s.io/v1alpha1"
Para este tutorial, é seguro ignorar os erros.
Agora que você instalou o plug-in de armazenamento da DigitalOcean, é possível criar armazenamento em bloco para armazenar o código da aplicação e os arquivos de configuração.
Com o seu Secret no lugar e o plug-in de armazenamento em bloco instalado, agora você está pronto para criar seu Volume Persistente. Um Volume Persistente, ou PV, é um armazenamento em bloco de um tamanho especificado que vive independentemente do ciclo de vida de um pod. O uso de um volume persistente lhe permitirá gerenciar ou atualizar seus pods sem se preocupar em perder o código da aplicação. Um Volume Persistente é acessado usando um PersistentVolumeClaim
ou PVC, que monta o PV no caminho especificado.
Abra um arquivo chamado code_volume.yaml
com seu editor:
- nano code_volume.yaml
Nomeie o PVC como code
adicionando os seguintes parâmetros e valores ao seu arquivo:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: code
A spec
para um PVC contém os seguintes itens:
accessModes
que variam de acordo com o caso de uso. Eles são:
ReadWriteOnce
– monta o volume como leitura e gravação para um único nodeReadOnlyMany
– monta o volume como somente leitura para muitos nodesReadWriteMany
– monta o volume como leitura e gravação par muitos nodesresources
– o espaço de armazenamento que você precisaO armazenamento em bloco da DigitalOcean é montado apenas em um único node, portanto, você definirá o accessModes
como ReadWriteOnce
. Este tutorial o guiará na adição de uma pequena quantidade de código da aplicação, portanto, 1 GB será suficiente nesse caso de uso. Se você planeja armazenar uma quantidade maior de código ou dados no volume, pode modificar o parâmetro storage
para atender aos seus requisitos. Você pode aumentar a quantidade de armazenamento após a criação do volume, mas a redução do disco não é suportada.
...
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Em seguida, especifique a classe de armazenamento que o Kubernetes usará para provisionar os volumes. Você usará a classe do-block-storage
criada pelo plug-in de armazenamento em bloco da DigitalOcean.
...
storageClassName: do-block-storage
O seu arquivo code_volume.yaml
ficará assim:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: code
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: do-block-storage
Salve e saia do arquivo.
Crie o PVC code
usando kubectl
:
- kubectl apply -f code_volume.yaml
A saída a seguir informa que o objeto foi criado com sucesso e você está pronto para montar seu PVC de 1 GB como um volume.
Outputpersistentvolumeclaim/code created
Para visualizar os Volumes Persistentes (PV) disponíveis:
- kubectl get pv
Você verá seu PV listado:
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
Os campos acima são uma visão geral do seu arquivo de configuração, exceto Reclaim Policy
e Status
. A Reclaim Policy
ou política de recuperação define o que é feito com o PV depois que o PVC que o está acessando é excluído. Delete
remove o PV do Kubernetes e da infraestrutura da DigitalOcean. Você pode aprender mais sobre Reclaim Policy
e Status
na documentação do Kubernetes PV.
Você criou com sucesso um Volume Persistente usando o plug-in de armazenamento em bloco da DigitalOcean. Agora que seu volume persistente está pronto, você criará seus pods usando um Deployment.
Nesta etapa, você aprenderá como usar um Deployment para criar seu pod PHP-FPM. Os Deployments fornecem uma maneira uniforme de criar, atualizar e gerenciar pods usando ReplicaSets.
A chave spec.selector
do Deployment listará as labels dos pods que ela gerenciará. Ela também usará a chave template
para criar os pods necessários.
Este passo também apresentará o uso de Init Containers. Init Containers executa um ou mais comandos antes dos containers regulares especificados na chave template
do pod. Neste tutorial, seu Init Container buscará um arquivo de exemplo index.php
no GitHub Gist usando o wget. Este é o conteúdo do arquivo de amostra:
<?php
echo phpinfo();
Para criar seu Deployment, abra um novo arquivo chamado php_deployment.yaml
com seu editor:
- nano php_deployment.yaml
Este Deployment gerenciará seus pods do PHP-FPM, assim você nomeará o objeto do Deployment como php
. Os pods pertencem à camada de back-end, portanto, você agrupará o Deployment nesse grupo usando a label tier: backend
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: php
labels:
tier: backend
Para o Deployment spec
, você especificará quantas cópias deste pod criar usando o parâmetro replicas
. O número de replicas
irá variar dependendo de suas necessidades e recursos disponíveis. Você criará uma réplica neste tutorial:
...
spec:
replicas: 1
Este Deployment gerenciará os pods que correspondem às labels app: php
e tier: backend
. Sob a chave seletor
, adicione:
...
selector:
matchLabels:
app: php
tier: backend
A seguir, o Deployment spec
requer o template
para a definição de objeto do seu pod. Este template ou modelo definirá especificações para a criação do pod. Primeiro, você adicionará as labels que foram especificadas para os seletores ou selectors
do serviço php e os matchLabels
do Deployment. Adicione app: php
e tier: backend
sob template.metadata.labels
:
...
template:
metadata:
labels:
app: php
tier: backend
Um pod pode ter vários containers e volumes, mas cada um precisará de um nome. Você pode montar seletivamente volumes em um container, especificando um caminho de montagem para cada volume.
Primeiro, especifique os volumes que seus containers acessarão. Você criou um PVC chamado code
para armazenar o código da aplicação, portanto, nomeie esse volume como code
. Sob spec.template.spec.volumes
, adicione o seguinte:
...
spec:
volumes:
- name: code
persistentVolumeClaim:
claimName: code
Em seguida, especifique o container que você deseja executar neste pod. Você pode encontrar várias imagens na Docker store, mas neste tutorial você usará a imagem php:7-fpm
.
Sob spec.template.spec.containers
, adicione o seguinte:
...
containers:
- name: php
image: php:7-fpm
Em seguida, você montará os volumes aos quais o container requer acesso. Este container executará seu código PHP e, portanto, precisará acessar o volume code
. Você também usará mountPath
para especificar /code
como o ponto de montagem.
Sob spec.template.spec.containers.volumeMounts
, adicione:
...
volumeMounts:
- name: code
mountPath: /code
Agora que você montou seu volume, é necessário inserir o código da sua aplicação no volume. Você pode ter usado anteriormente FTP/SFTP ou clonado o código em uma conexão SSH para fazer isso, mas este passo mostrará como copiar o código usando um Init Container.
Dependendo da complexidade do seu processo de instalação, você pode usar um único initContainer
para executar um script que constrói sua aplicação, ou você pode usar um initContainer
por comando. Certifique-se de que os volumes estejam montados no initContainer
.
Neste tutorial, você usará um único Init Container com busybox
para baixar o código. busybox
é uma pequena imagem que contém o utilitário wget
que você usará para fazer isso.
Sob spec.template.spec
, adicione seu initContainer
e especifique a imagem busybox
:
...
initContainers:
- name: install
image: busybox
Seu Init Container precisará acessar o volume do code
para que possa fazer o download do código nesse local. Sob spec.template.spec.initContainers
, monte o volume code
no caminho /code
:
...
volumeMounts:
- name: code
mountPath: /code
Cada Init Container precisa executar um comando
. Seu Init Container usará o wget
para baixar o código a partir do Github dentro do diretório de trabalho /code
. A flag -O
atribui um nome ao arquivo baixado e você nomeará esse arquivo como index.php
.
Nota: Certifique-se de confiar no código que você está enviando. Antes de baixá-lo para o seu servidor, inspecione o código-fonte para garantir que você esteja confortável com o que o código faz.
Abaixo do container install
em spec.template.spec.initContainers
, adicione estas linhas:
...
command:
- wget
- "-O"
- "/code/index.php"
- https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php
Seu arquivo php_deployment.yaml
completo será semelhante a este:
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
Salve o arquivo e saia do editor.
Crie o deployment PHP-FPM com o kubectl
:
- kubectl apply -f php_deployment.yaml
Você verá a seguinte saída na criação do Deployment:
Outputdeployment.apps/php created
Para resumir, esse Deployment começará baixando as imagens especificadas. Ele então solicitará o PersistentVolume
do seu PersistentVolumeClaim
e executará em série o seu initContainers
. Depois de concluídos, os containers irão executar e montar os volumes
no ponto de montagem especificado. Quando todas essas etapas estiverem concluídas, seu pod estará em funcionamento.
Você pode visualizar seu Deployment executando:
- kubectl get deployments
Você verá a saída:
OutputNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
php 1 1 1 0 19s
Esta saída pode ajudá-lo a entender o estado atual do Deployment. Um Deployment
é um dos controladores que mantém um estado desejado. O template
que você criou especifica que o estado desejado ou DESIRED
terá 1 replicas
do pod chamado php
. O campo CURRENT
indica quantas réplicas estão executando, portanto, isso deve corresponder ao estado DESIRED
. Você pode ler sobre os campos restantes na documentação do Kubernetes Deployments.
Você pode visualizar os pods que esse Deployment iniciou com o seguinte comando:
- kubectl get pods
A saída deste comando varia dependendo de quanto tempo se passou desde a criação do Deployment. Se você executá-lo logo após a criação, a saída provavelmente será assim:
OutputNAME READY STATUS RESTARTS AGE
php-86d59fd666-bf8zd 0/1 Init:0/1 0 9s
As colunas representam as seguintes informações:
Ready
: O número de replicas
executando nesse pod.Status
: O status do pod. Init
indica que os Init Containers estão executando. Nesta saída, 0 de 1 Init Containers terminaram a execução.Restarts
: Quantas vezes esse processo foi reiniciado para iniciar o pod. Esse número aumentará se algum dos seus Init Containers falhar. O Deployment irá reiniciá-lo até atingir o estado desejado.Dependendo da complexidade dos seus scripts de inicialização, pode levar alguns minutos para que o status mude para podInitializing
:
OutputNAME READY STATUS RESTARTS AGE
php-86d59fd666-lkwgn 0/1 podInitializing 0 39s
Isso significa que os Init Containers foram finalizados e os containers estão inicializando. Se você executar o comando quando todos os containers estiverem em execução, o status do pod será alterado para Running
.
OutputNAME READY STATUS RESTARTS AGE
php-86d59fd666-lkwgn 1/1 Running 0 1m
Agora você vê que seu pod está sendo executado com êxito. Se o seu pod não iniciar, você poderá depurar com os seguintes comandos:
- kubectl describe pods nome-do-pod
- kubectl logs nome-do-pod
- kubectl logs nome-do-pod nome-do-container
O código da sua aplicação está montado e o serviço PHP-FPM está pronto para lidar com as conexões. Agora você pode criar seu Deployment do Nginx.
Neste passo, você usará um ConfigMap para configurar o Nginx. Um ConfigMap mantém sua configuração em um formato de chave-valor que você pode referenciar em outras definições de objeto do Kubernetes. Essa abordagem concederá a flexibilidade de reutilizar ou trocar a imagem por uma versão diferente do Nginx, se necessário. A atualização do ConfigMap replicará automaticamente as alterações em qualquer pod que o monte.
Crie um arquivo nginx_configMap.yaml
para seu ConfigMap com seu editor:
- nano nginx_configMap.yaml
Nomeie o ConfigMap como nginx-config
e agrupe-o no microsserviço tier: backend
:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
labels:
tier: backend
Em seguida, você adicionará os dados, data
, para o ConfigMap. Nomeie a chave como config
e adicione o conteúdo do seu arquivo de configuração do Nginx como o valor. Você pode usar o exemplo de configuração do Nginx deste tutorial.
Como o Kubernetes pode rotear solicitações para o host apropriado para um serviço, você pode inserir o nome do seu serviço PHP-FPM no parâmetro fastcgi_pass
em vez de seu endereço IP. Adicione o seguinte ao seu arquivo 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;
}
}
Seu arquivo nginx_configMap.yaml
será parecido com este:
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;
}
}
Salve o arquivo e saia do editor.
Crie o ConfigMap:
- kubectl apply -f nginx_configMap.yaml
Você verá a seguinte saída:
Outputconfigmap/nginx-config created
Você terminou de criar o seu ConfigMap e agora pode criar seu Deployment do Nginx.
Comece abrindo um novo arquivo nginx_deployment.yaml
no editor:
- nano nginx_deployment.yaml
Nomeie o Deployment como nginx
e adicione a label tier: backend
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
tier: backend
Especifique que você quer uma replicas
na spec
do Deployment. Esse Deployment gerenciará os pods com labels app: nginx
e tier: backend
. Adicione os seguintes parâmetros e valores:
...
spec:
replicas: 1
selector:
matchLabels:
app: nginx
tier: backend
Em seguida, adicione o template
do pod. Você precisa usar as mesmas labels que você adicionou para o Deployment selector.matchLabels
. Adicione o seguinte:
...
template:
metadata:
labels:
app: nginx
tier: backend
Dê ao Nginx acesso ao PVC code
que você criou anteriormente. Sob spec.template.spec.volumes
, adicione:
...
spec:
volumes:
- name: code
persistentVolumeClaim:
claimName: code
Os pods podem montar um ConfigMap como um volume. A especificação de um nome de arquivo e chave criará um arquivo com seu valor como conteúdo. Para usar o ConfigMap, defina path
como o nome do arquivo que armazenará o conteúdo da key
. Você deseja criar um arquivo site.conf
a partir da chave config
. Sob spec.template.spec.volumes
, adicione o seguinte:
...
- name: config
configMap:
name: nginx-config
items:
- key: config
path: site.conf
Atenção: Se um arquivo não for especificado, o conteúdo de key
substituirá o mountPath
ou o caminho de montagem do volume. Isso significa que, se um caminho não for especificado explicitamente, você perderá todo o conteúdo na pasta de destino.
A seguir, você especificará a imagem a partir da qual criar seu pod. Este tutorial usará a imagem nginx:1.7.9
para estabilidade, mas você pode encontrar outras imagens Nginx na Docker store. Além disso, torne o Nginx disponível na porta 80
. Sob spec.template.spec
, adicione:
...
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
O Nginx e o PHP-FPM precisam acessar o arquivo no mesmo caminho, portanto, monte o volume code
em /code
:
...
volumeMounts:
- name: code
mountPath: /code
A imagem nginx:1.7.9
carregará automaticamente quaisquer arquivos de configuração no diretório /etc/nginx/conf.d
. A montagem do volume config
neste diretório criará o arquivo /etc/nginx/conf.d/site.conf
. Sob volumeMounts
, adicione o seguinte:
...
- name: config
mountPath: /etc/nginx/conf.d
Seu arquivo nginx_deployment.yaml
será parecido com este:
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
Salve o arquivo e saia do editor.
Crie o Deployment do Nginx:
- kubectl apply -f nginx_deployment.yaml
A seguinte saída indica que seu Deployment foi criado agora:
Outputdeployment.apps/nginx created
Liste seus Deployments com este comando:
- kubectl get deployments
Você verá os Deployments Nginx e PHP-FPM:
OutputNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 1 1 1 0 16s
php 1 1 1 1 7m
Liste os pods gerenciados por ambos os deployments:
- kubectl get pods
Você verá os pods em execução:
OutputNAME READY STATUS RESTARTS AGE
nginx-7bf5476b6f-zppml 1/1 Running 0 32s
php-86d59fd666-lkwgn 1/1 Running 0 7m
Agora que todos os objetos do Kubernetes estão ativos, você pode visitar o serviço Nginx no seu navegador.
Liste os serviços em execução:
- kubectl get services -o wide
Obtenha o IP externo para o seu serviço 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 seu_ip_público 80/TCP 27m app=nginx,tier=backend
php ClusterIP 10.100.59.238 <none> 9000/TCP 34m app=php,tier=backend
No seu navegador, visite seu servidor digitando http://seu_ip_público
. Você verá a saída de php_info()
e irá confirmar que seus serviços do Kubernetes estão funcionando.
Neste guia, você containerizou os serviços PHP-FPM e Nginx para poder gerenciá-los independentemente. Essa abordagem não apenas melhorará a escalabilidade do seu projeto à medida que você cresce, mas também permitirá que você use os recursos com eficiência. Você também armazenou o código da sua aplicação em um volume para poder atualizar facilmente seus serviços no 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!