
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.
I’m a consultant and technical expert in Linux, Datacenter, and Cloud. I've been worked with Customer Support because I love helping people.
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!
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.