Voltar ao blog

Implantar uma aplicação PHP em um cluster Kubernetes com Ubuntu 18.04

Implantar uma aplicação PHP em um cluster Kubernetes com Ubuntu 18.04

Kubernetes (também conhecido como k8s) é um sistema de orquestração de código aberto. Ele permite que os usuários implantem, dimensionem e gerenciem aplicativos em contêineres com o mínimo de tempo de inatividade. Neste tutorial, você aprenderá como implantar um aplicativo PHP em um Cluster Kubernetes.

O Nginx se comporta como um proxy para o PHP-FPM ao executar um aplicativo PHP. Gerenciar esses dois serviços em um único contêiner é um processo difícil. O Kubernetes nos ajuda a gerenciá-los em dois contêineres diferentes e reduz o incômodo. Ele também permite que os usuários reutilizem os contêineres e não se preocupem em criar sua imagem de contêiner para cada nova versão do PHP/Nginx.

Você executará seu aplicativo e o serviço de proxy em dois contêineres separados. O tutorial também fornecerá informações sobre como usar o armazenamento local para criar um Persistent Volume (PV) e uma Reivindicação de Volume Persistente (PVC). Você usará essa PVC para manter seus arquivos de configuração e código fora das imagens do contêiner. Depois de concluir este tutorial, você poderá reutilizar sua imagem do Nginx para outros aplicativos que exigem um servidor proxy. Você pode conseguir isso passando uma configuração, em vez de reconstruir a imagem para isso.

Pré-requisitos

  1. Uma compreensão básica do Kubernetes (k8s) e de seus objetos. Consulte este guia para obter uma visão geral detalhada do ecossistema Kubernetes.
  2. Um cluster Kubernetes que esteja ativo e em execução no Ubuntu 18.04. Siga este tutorial para criar seu cluster Kubernetes usando o kubeadm.
  3. Além disso, você precisa hospedar o código do seu aplicativo em uma URL pública, por exemplo, GitHub.

Passo 1: Criar os Serviços PHP-FPM e Nginx

Este passo ajudará você a criar os serviços PHP-FPM e Nginx. Qualquer serviço fornece acesso a um conjunto de pods dentro de um cluster. Todos os serviços presentes em um cluster podem se comunicar entre si com seus nomes, sem endereços IP. O serviço PHP-FPM e o serviço Nginx fornecerão acesso aos pods PHP-FPM e Nginx, respectivamente.

Você precisará dizer ao serviço PHP-FPM como encontrar os pods do Nginx, pois ele agirá como um proxy para os pods do PHP-FPM. Para isso, você aproveitará a descoberta automática de serviços do Kubernetes’ e usará nomes legíveis por humanos para rotear a solicitação para o respectivo serviço.

Para criar qualquer serviço, você precisará criar um arquivo YAML que contém a definição do objeto. Este arquivo YAML tem pelo menos as seguintes tags:

  1. apiVersion: A versão da API do Kubernetes à qual a definição pertence.
  2. kind: O tipo (kind) de objeto do Kubernetes que este arquivo YAML cria. Por exemplo: um service, um job, ou um pod.
  3. metadata: O nome do objeto e as diferentes labels que o usuário pode querer aplicar a este objeto são definidas sob esta tag.
  4. spec: Esta tag contém a especificação do seu objeto, como ENVs, imagem de contêiner a ser usada, portas nas quais o serviço do contêiner estará acessível.
Criando o serviço PHP-FPM

Para começar, você deve criar um diretório para manter a definição do seu objeto do Kubernetes. Faça login no seu nó mestre e crie um diretório chamado “definitions:”

Altere o diretório para o diretório definitions:

Em seguida, crie seu arquivo de serviço PHP-FPM como o arquivo php_service.yaml:

Depois disso, defina o apiVersion e o kind no arquivo php_fpm_service.yaml:

Nomeie seu serviço como php ou php-fpm, pois ele fornecerá acesso ao seu aplicativo PHP-FPM:

Rotule seu serviço php como tier: backend, pois o aplicativo PHP será executado atrás deste serviço:

Um serviço usa os rótulos de selector para determinar quais pods acessar. Qualquer pod que corresponda a esses rótulos, independentemente de quando o pod foi criado, é atendido. Você aprenderá como adicionar rótulos aos seus pods mais adiante neste tutorial.

Inclua o tier: backend rótulo que atribui o seu pod à camada backend, junto com o app: php-fpm rótulo para indicar que o pod executa uma aplicação PHP-FPM. Você deve adicionar esses rótulos após a metadata seção:

Em seguida, você precisa declarar a porta para acessar este php-fpm serviço sob spec. Você pode adicionar qualquer porta de sua escolha, mas usaremos a porta 9000 neste tutorial:

Depois de concluir as etapas acima, o seu arquivo php_fpm_service.yaml ficará assim:

Pressione Ctrl + O para salvar o arquivo, depois pressione Ctrl + X para sair do nano.

Aplicando o comando kubectl para criar o serviço PHP

Assim que a definição do objeto para o seu serviço for criada, execute o comando kubectl apply com o argumento -f especificando o seu arquivo php_fpm_service.yaml:

A saída do comando acima deve ser:

Execute o comando abaixo para verificar se o seu serviço php-fpm está em execução:

Você poderá ver o serviço php-fpm ativo e em execução:

Nota: O Kubernetes suporta vários tipos de serviços. O seu serviço php-fpm 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 Kubernetes.
Criando o serviço Nginx

Como o seu serviço PHP-FPM já está pronto, é hora de criar também o seu serviço Nginx. Crie e abra um novo arquivo YAML para este serviço, chamado nginx_service.yaml no editor:

Nomeie este serviço como nginx pois ele terá como alvo os pods do Nginx. Este serviço também pertence ao backend, então você deve adicionar um rótulo tier: backend a ele:

Como fizemos no serviço php-fpm, adicione os rótulos seletores app: nginx e tier: backend para direcionar aos pods. Adicione a porta HTTP padrão 80 para acessar este serviço:

O serviço Nginx pode ser acessado publicamente na internet a partir do endereço IP público. Você pode adicionar o IP do seu nó de trabalho como your_public_ip. Adicione as linhas abaixo sob spec.externalIPs:

O seu arquivo nginx_service.yaml deve se parecer com o abaixo depois de concluir todas as etapas acima:

Salve e feche o arquivo após adicionar todos os parâmetros necessários acima.

Aplicando o comando kubectl para criar o serviço Nginx
Você deve ver a saída abaixo para o comando acima:
Agora, execute o seguinte comando para visualizar todos os seus serviços em execução:
Ao executar o comando acima, você deverá ver os seus serviços PHP-FPM e Nginx ativos e em execução:
Observe que, se desejar excluir qualquer um dos seus serviços em execução, você pode executar o comando abaixo:

Passo 2: Criar Armazenamento Local e Volume Persistente

O Kubernetes fornece vários plug-ins de armazenamento que ajudam você a criar espaço de armazenamento para o seu ambiente. Este passo irá guiá-lo sobre como criar uma StorageClass local e como esta Storage Class pode ser usada posteriormente para criar um Volume Persistente.

Criando um armazenamento local

Crie um arquivo, por exemplo, storageClass.yaml, no seu editor:

Adicione o kind como "storageClass" e o apiVersion como "storage.k8s.io/v1" da seguinte forma:

Nomeie esta StorageClass como "my-local-storage" e adicione o provisioner e o volumeBindingMode da seguinte forma:

Salve e saia do arquivo e o seu arquivo final storageClass.yaml deve se parecer com isto:

Agora, crie a StorageClass executando o comando kubectl create, como abaixo:

Após executar o comando acima, você deve obter a saída abaixo:

Criando Volume Persistente local

Depois de criar o Armazenamento Local, você pode criar o seu Volume Persistente local. Um Volume Persistente, também conhecido como PV, é o armazenamento em bloco de tamanho especificado que é independente do ciclo de vida de um pod. Um Volume Persistente local nada mais é do que um disco local ou um diretório que está disponível em um nó do cluster Kubernetes. Este Volume Persistente local permite que seus usuários acessem o armazenamento local usando uma Solicitação de Volume Persistente (Persistent Volume Claim) local de uma maneira muito simples e portátil. Você pode criar este Volume Persistente local usando esta classe de armazenamento que acabamos de criar. Abra um arquivo, por exemplo, persistentVolume.yaml, no seu editor:

Dê um nome a este volume persistente, por exemplo, "my-local-pv":

Você pode adicionar capacidade de armazenamento de acordo com o seu uso ao criar um Volume Persistente local. Neste tutorial, usaremos 5 Gi para o armazenamento:

Adicione os accessModes, persistentVolumeReclaimPolicy e forneça o mesmo storageClassName usado em storageClass.yaml:

Nota: persistentVolumeReclaimPolicy informa o que acontece com o Persistent Volume assim que sua reivindicação (Persistent Volume Claim) é liberada. Existem três opções válidas para este parâmetro: Retain, Delete e Recycle. Em nosso código, usaremos a opção Retain. Para mais detalhes, você pode verificar o campo persistentVolumeReclaimPolicy aqui: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#persistentvolumeclaim-v1-core

Adicione o local.path para o seu Persistent Volume conforme abaixo:

Nota: Certifique-se de que este caminho local (/mnt/disk/vol) exista no nó do seu cluster Kubernetes.

Depois de adicionar todos os campos obrigatórios, o seu arquivo persistentVolume.yaml deve ficar assim:

Nota: Você deve usar o nome de nó correto da sua máquina. Neste caso, é: “worker.”
Preparando o Volume Local

Agora, precisamos preparar um volume local no nó “worker” conforme adicionamos no arquivo persistentVolume.yaml . Execute os comandos abaixo no nó que você configurou no persistentVolume. Neste caso, é o nó “worker”:

Nota: Certifique-se de ter permissão suficiente para criar o diretório e alterar a permissão conforme mostrado acima. Caso contrário, execute os comandos com o usuário correto.

Execute o comando abaixo no nó master onde o seu arquivo persistentVolume.yaml está presente:

Você deve obter a seguinte saída:

Como você criou com sucesso seu armazenamento local e o Persistent Volume, agora você pode prosseguir e criar um Persistent Volume Claim para conter o código do seu aplicativo e os arquivos de configuração.

Etapa 3: Criar o Persistent Volume

O código do seu aplicativo precisa ser mantido seguro enquanto você gerencia ou atualiza seus pods. Para isso, você usará o Persistent Volume, criado na etapa anterior, que é acessado usando um PersistentVolumeClaim, ou PVC. Este PVC monta o PV no caminho necessário.

Abra um arquivo, por exemplo, code_volume.yaml, no seu editor:

Nomeie seu PVC como code adicionando os parâmetros e valores abaixo ao seu arquivo:

A seção spec de um PVC possui os seguintes itens:

  1. accessModes: Existem vários valores possíveis para este campo, conforme a seguir:
    • ReadWriteOnce – Monta o volume para um único nó com permissões de leitura e gravação.
    • ReadOnlyMany – Monta o volume para vários nós com apenas permissão de leitura.
    • ReadWriteMany – Monta o volume para vários nós com permissões de leitura e gravação.
  2. resources: Define o espaço de armazenamento necessário.

Como o armazenamento local é montado em apenas um único nó, você precisará definir o accessMode como ReadWriteOnce. Neste tutorial, você adicionará apenas uma pequena parte do código da aplicação, portanto, 1 GB de armazenamento será suficiente aqui. No entanto, se desejar armazenar uma quantidade maior de dados ou código, poderá modificar o parâmetro de armazenamento de acordo com suas necessidades. Observe que, assim que o volume for criado, você poderá aumentar o tamanho do armazenamento. No entanto, a redução não é suportada:

Agora, declare a classe de armazenamento que o cluster Kubernetes usará para alocar aos volumes. Use a classe de armazenamento my-local-storage, criada na etapa anterior, aqui para o seu storageClassName:

Após concluir as etapas acima, o seu code_volume.yaml arquivo deve ficar assim:

Agora salve e saia do arquivo.

Criando o PVC

Crie o PVC code executando o comando kubectl apply:

Você deve obter a seguinte saída que indica que o objeto foi criado com sucesso e está pronto para poder montar seu PVC de 1 GB como volume:

Você pode executar o seguinte comando para verificar o Volume Persistente (PV) disponível:

A saída do comando acima deve ser a seguinte:

Todos os campos acima, exceto Reclaim Policy e Status, são uma visão geral do seu arquivo de configuração. A Reclaim Policy define o que acontece com o PV assim que o PVC que o acessa é excluído. O valor Delete remove o PV do cluster Kubernetes, bem como da infraestrutura de armazenamento. Você pode consultar a documentação de PV do Kubernetes para ter uma compreensão clara de Reclaim Policy e Status.

Agora você pode criar seus pods usando um Deployment, pois criou com sucesso seu Volume Persistente usando o armazenamento local.

Etapa 4: Criar o Deployment para sua aplicação PHP-FPM

Esta etapa ajudará você a criar seu pod PHP-FPM usando o Deployment. O Deployment usa ReplicaSets para fornecer uma maneira estável de criar, atualizar e gerenciar seus pods. Um Deployment reverte automaticamente seus pods para uma imagem anterior.

A spec.selector chave no Deployment lista todas as labels dos pods que ele gerencia. Ele também usa a chave template para criar os pods necessários.

Nesta etapa, também introduziremos a aplicação de Init Containers. Os Init Containers executam alguns comandos antes dos containers regulares especificados sob o template do pod. Aqui, o Init Container usará o GitHub Gist (https://gist.github.com/) para obter um index.php de exemplo. O conteúdo do arquivo de exemplo é:

Criando o Deployment do PHP

Abra um novo arquivo chamado php_deployment.yaml no seu editor para criar seu Deployment:

Agora, nomeie o objeto Deployment como PHP, pois este Deployment gerenciará seus pods PHP-FPM. Adicione o rótulo tier: backend porque o pod pertencerá à camada backend:

Usando o parâmetro replica, especifique o número de cópias deste pod que devem ser criadas. O número de réplicas pode variar com base nos seus requisitos e nos recursos disponíveis. Neste tutorial, você criará apenas uma réplica do seu pod:

Adicione app: php e tier:backend sob a chave selector que indica que este Deployment gerenciará pods que correspondem a esses dois rótulos:

Agora, a definição do objeto do seu pod precisa de um template sob a especificação do seu Deployment. Este template define a especificação necessária para criar o seu pod. Para começar, adicione os rótulos que foram especificados para o seletor de serviço php e o matchLabels do Deployment. Em seguida, adicione app:php e tier:backend sob template.metadata.labels:

Note: Um pod pode ter múltiplos contêineres ou volumes e cada um deles precisará de um nome diferente para poder diferenciá-los.  Você pode especificar um caminho de montagem para cada volume para montar seletivamente esse volume em um contêiner.

First, you need to specify all the volumes that your containers will access. Name this volume code as you had created a PVC named code to hold your application code:

Em seguida, especifique o nome do contêiner junto com a imagem que você deseja executar dentro do seu pod. Existem várias imagens disponíveis na Docker store (https://hub.docker.com/explore/), mas neste tutorial, usaremos a imagem php:7-fpm:

Agora, monte os volumes aos quais o contêiner precisa de acesso. Como este contêiner executará seu código php, ele precisará de acesso ao volume code criado na etapa anterior. Nesta etapa, você também aprenderá como copiar o código da sua aplicação usando o Init Container.

Note: Você pode usar um único initContainer para executar um script que compila sua aplicação ou pode usar um initContainer por comando, dependendo da complexidade do seu processo de configuração. Você precisa garantir que os volumes estejam montados no initContainer.

To download the code, this tutorial will guide you on how to use a single Init Container with busybox. Busybox is a small container with wget utility that you will use to achieve this.

First, add your initContainer under spec.template.spec e especifique a imagem busybox:

Depois, para baixar o código no volume code, seu Init Container precisará de acesso a ele. Monte o volume code no caminho /code sob spec.template.spec.initContainers:

Todo Init Container precisa executar um comando. Este Init Container usará o wget para baixar o code do Github para o diretório /code. Você pode passar uma opção -O para dar um nome a este arquivo baixado, e você pode nomear este arquivo como index.php.

Note: Certifique-se de confiar no código que você está trazendo para o seu servidor usando o Init Container. Você pode inspecionar o código-fonte e garantir que está confortável com o que ele faz.

Além disso, adicione as linhas abaixo sob o contêiner install em spec.template.spec.initContainers:

Depois de concluir todas essas etapas, o seu php_deployment.yaml arquivo deve se parecer com isto:

Agora você pode salvar o arquivo e sair. Em seguida, crie o seu Deployment PHP-FPM usando o kubectl apply comando:

A criação bem-sucedida do Deployment deve fornecer a saída abaixo:

Este Deployment começa baixando as imagens especificadas, depois solicitará o PersistentVolume do seu PersistentVolumeClaim, e depois executará os seus initContainers. Assim que esta etapa for concluída, os contêineres serão executados e montarão os volumes no ponto de montagem especificado. Depois de concluir todas essas etapas, o seu pod estará ativo e em execução.

Você pode executar o comando abaixo para visualizar o seu Deployment:

Depois de executar o comando acima, você deve obter a saída abaixo:

Você pode entender o estado atual do Deployment com a ajuda desta saída. Um Deployment é um controlador que mantém o estado desejado. O DESEJADO campo especifica que ele possui 1 réplica do pod chamado php. O ATUAL campo indica quantas réplicas do DESEJADO estado estão em execução no momento. Para um pod saudável, isso deve corresponder ao DESEJADO estado. Você pode aprender mais sobre os campos restantes na Documentação de Deployments do Kubernetes.

Depois disso, para verificar o status do seu pod em execução, você pode executar o comando abaixo:

A saída deste comando pode variar dependendo do tempo decorrido desde que você criou o seu Deployment. Se for executado logo após a criação do Deployment, a saída será semelhante a:

Explicação:

Estas colunas representam as informações abaixo:

  • Ready: O número de réplicas atuais/desejadas executando este pod.
  • Status: O status do seu pod. Init:0/1 indica que os Init Containers estão em execução e 0 de 1 Init Containers concluíram a execução.
  • Restarts: Isso indica o número de vezes que este processo foi reiniciado para iniciar o pod.

Seu pod pode levar alguns minutos para que o status mude para podInitializing dependendo da complexidade dos seus scripts de inicialização:

Isso indica que os Init Containers foram executados com sucesso e agora os containers estão inicializando:

Como você pode ver agora, seu pod está ativo e em execução. No entanto, caso seu pod não inicie, você pode executar os comandos abaixo para fins de depuração:

1. Para visualizar informações detalhadas do pod:

2.  Para visualizar os logs do pod:

Nota: Existem várias opções disponíveis para o comando “kubectl logs”, você pode executar o comando “kubectl logs –help” para explorar mais sobre isso.

3. Para visualizar os logs de um container específico no pod:

Parabéns! Você montou com sucesso o código da aplicação e o serviço PHP-FPM está pronto para lidar com conexões. Da mesma forma, você pode criar seu Deployment do Nginx.

Passo 5: Crie seu Deployment do Nginx

Este passo guiará você sobre como configurar o Nginx usando um ConfigMap. Um ConfigMap mantém todas as suas configurações necessárias em um formato de chave-valor que será usado em outras definições de objetos do Kubernetes. Com essa abordagem, você terá a flexibilidade de reutilizar ou trocar a imagem do Nginx por uma versão diferente, conforme e quando necessário. Você pode atualizar o ConfigMap e ele replicará automaticamente essas alterações para qualquer pod que esteja montando este ConfigMap.

Para começar, abra um arquivo nginx_configmap.yaml no seu editor:

Agora, nomeie este ConfigMap como nginx-config e adicione-o ao tier: backend microserviço:

Além disso, você pode adicionar os dados ao ConfigMap. Adicione uma chave chamada config e adicione todo o conteúdo do arquivo de configuração do Nginx como o valor.

Como é possível para o Kubernetes rotear requisições para os respectivos hosts de um serviço, você pode inserir o nome do seu serviço PHP-FPM sob o parâmetro fastcgi_pass em vez do seu endereço IP. Adicione as seguintes linhas de código ao seu arquivo nginx_configMap.yaml :

Depois de concluído, o seu nginx_configMap.yaml arquivo ficará assim:

Agora você pode salvar e sair do editor. Agora execute o kubectl apply o comando para criar o ConfigMap:

Depois disso, você deverá ver a saída abaixo na sua tela:

Você criou com sucesso o seu Configmap do Nginx. Agora você pode criar o seu Deployment do Nginx.

Criando o Deployment do Nginx

Para começar, você pode criar um novo arquivo chamado nginx_deployment.yaml no editor:

Nomeie este Deployment como nginx e adicione o rótulo tier: backend a ele:

Depois disso, especifique a contagem de réplicas adicionando o campo replica na especificação do Deployment e adicione os rótulos app: nginx e tier: backend a ele:

Da mesma forma, adicione o modelo de pod. Certifique-se de adicionar os mesmos rótulos que você adicionou no selector.matchLabels do Deployment. Você pode adicionar o seguinte:

Dê ao Nginx acesso ao PVC code que foi criado anteriormente adicionando os seguintes parâmetros sob spec.template.spec.volumes:

Nota: Um pod pode montar o ConfigMap como um volume. Ao especificar o nome do arquivo e a chave, criaremos um arquivo com seu valor como conteúdo. Para usar este ConfigMap, defina o caminho para o nome do arquivo que contém o conteúdo da chave. Você pode criar um arquivo site.conf a partir da chave config. Adicione o seguinte sob spec.template.spec.volumes:

Aviso: O conteúdo da chave substituirá o mountPath do volume se um arquivo não for especificado. Em outras palavras, você perderá todo o conteúdo na pasta de destino se um caminho não for explicitamente especificado.

Agora, especifique o nome, a imagem e a porta que você deseja usar em seu pod. Aqui, usaremos a imagem nginx:1.7.9 e a porta 80. Adicione-os sob spec.template.spec seção:

Além disso, monte o volume de código em /code pois tanto o Nginx quanto o PHP-FPM precisarão acessar o arquivo no mesmo caminho:

A imagem nginx-1.7.9 carrega automaticamente qualquer arquivo de configuração sob a pasta /etc/nginx/conf.d. Agora, se montarmos o volume de configuração neste diretório, ele criará /etc/nginx/conf.d/site.conf. Adicione o seguinte sob a seção volumeMount:

Depois de concluir todas as etapas acima, seu arquivo nginx_deployment.yaml deve ficar assim:

Agora você pode salvar e sair do arquivo e criar o Deployment do Nginx executando o seguinte comando:

Após a execução bem-sucedida do comando, você deverá ver a seguinte saída:

Você pode listar todos os seus Deployments executando os comandos abaixo:

Agora você deve ver os Deployments do Nginx e do PHP-FPM:

kubernetes deployment status

Além disso, você pode executar o seguinte comando para listar os pods que são gerenciados por ambos os Deployments listados acima:

Você verá que ambos os seus pods estão ativos e em execução como a seguir:

kubernetes pod status

Como todos os seus objetos do Kubernetes estão ativos neste momento, agora você pode acessar o serviço Nginx no seu navegador.

Execute o seguinte comando para listar os serviços:

Anote o IP Externo do seu serviço Nginx:external ip of nginx Deploy a PHP Application on Kubernetes Cluster with Ubuntu 18.04

Agora, usando este IP Externo do serviço Nginx, você pode visitar o seu servidor digitando http://your_public_ip no seu navegador. Você deverá conseguir ver a saída do php_info() que confirma que os seus serviços do Kubernetes estão ativos e em execução.

Conclusão

Neste tutorial, para gerenciar seus serviços PHP-FPM e Nginx de forma independente, você conteinerizou os dois serviços. Ao fazer isso, você não apenas melhorará a escalabilidade do seu projeto, mas também usará seus recursos de maneira eficiente. Você também aprendeu como criar armazenamento local e um Volume Persistente para armazenar o código da sua aplicação em um volume e poder atualizar facilmente seus serviços no futuro. Ao fazer isso, você melhorou a usabilidade e a manutenibilidade do seu código.

Além disso, dê uma olhada em nossos outros tutoriais focados em Docker e Kubernetes que você pode encontrar em nosso blog:

Boa computação!

author

Hark Labs

Autor · CloudSigma

Preslav Dobrev é um designer criativo na CloudSigma, focado na construção de uma identidade empresarial consistente por meio de canais de marketing tradicionais e inovadores. Ele é hábil em combinar a visão artística com o marketing estratégico para criar narrativas de marca impactantes.

Comentários

Nenhum comentário ainda. Seja o primeiro.