Atividade 04 - Recursos Básicos do Kubernetes

Namespaces

Criar um Namespace no Kubernetes utilizando dois métodos: imperativo (linha de comando) e declarativo (arquivo YAML).

Parte 1: Criando um Namespace de forma Imperativa

Utilize o comando abaixo para criar um Namespace chamado meu-namespace:

kubectl create namespace meu-namespace

Verifique se o Namespace foi criado:

kubectl get namespaces

Delete o Namespace criado:

kubectl delete namespace meu-namespace

Parte 2: Criando um Namespace de forma Declarativa

Crie um arquivo chamado namespace.yaml com o seguinte conteúdo:

apiVersion: v1
kind: Namespace
metadata:
  name: meu-namespace

Aplique o arquivo para criar o Namespace:

kubectl apply -f namespace.yaml

Confirme a criação do Namespace:

kubectl get namespaces

Para remover o Namespace, use:

kubectl delete -f namespace.yaml

Comandos úteis

Para listar recursos de um Namespace:

kubectl --namespace meu-namespace get pods
# pode ser abreviado para "-n meu-namespace"

Definir um Namespace padrão para comandos do kubectl

kubectl config set-context --current --namespace meu-namespace

ConfigMaps

ConfigMap com variáveis de ambiente

Crie um arquivo chamado app-configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_MODE: "production"
  APP_DEBUG: "false"

Aplique:

kubectl apply -f app-configmap.yaml

Crie um arquivo chamado app-deploy-env.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: configmap-env-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: configmap-env
  template:
    metadata:
      labels:
        app: configmap-env
    spec:
      containers:
        - name: alpine
          image: alpine
          command: ["sh", "-c", "env && sleep 3600"]
          envFrom:
            - configMapRef:
                name: app-config

Aplique:

kubectl apply -f app-deploy-env.yaml

Verificar variáveis no container

Liste os Pods:

kubectl get pods

Entre no container:

kubectl exec -it <nome-do-pod> -- sh

Veja as variáveis de ambiente:

echo $APP_MODE
echo $APP_DEBUG

ConfigMap como arquivos

Crie um arquivo chamado configmap-arquivos.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-files
data:
  app.conf: |
    APP_NAME=MinhaApp
    APP_VERSION=1.0
  log.properties: |
    level=debug
    output=stdout

Aplique o ConfigMap:

kubectl apply -f configmap-arquivos.yaml

Crie um arquivo chamado deployment-arquivos.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-com-configmap-arquivo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: configmap-arquivo
  template:
    metadata:
      labels:
        app: configmap-arquivo
    spec:
      containers:
        - name: app
          image: busybox
          command: ["sh", "-c", "cat /config/app.conf && cat /config/log.properties && echo && sleep 3600"]
          volumeMounts:
            - name: config-volume
              mountPath: /config
      volumes:
        - name: config-volume
          configMap:
            name: app-config-files

Aplique:

kubectl apply -f deployment-arquivos.yaml

Verificar o conteúdo dos arquivos montados

Veja os logs do Pod:

kubectl logs -l app=configmap-arquivo

Você deve ver:

APP_NAME=MinhaApp
APP_VERSION=1.0
level=debug
output=stdout

Secrets

Usando Secrets como Variáveis de Ambiente

Criar o Secret

kubectl create secret generic meu-secret \
  --from-literal=DB_USER=admin \
  --from-literal=DB_PASS=supersecreta

Verifique:

kubectl describe secret meu-secret

Criar o Deployment que injeta o Secret como env

Crie um arquivo deployment-secret-env.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-com-secret-env
spec:
  replicas: 1
  selector:
    matchLabels:
      app: secret-env
  template:
    metadata:
      labels:
        app: secret-env
    spec:
      containers:
        - name: busybox
          image: busybox
          command: ["sh", "-c", "echo DB_USER=$DB_USER && echo DB_PASS=$DB_PASS && sleep 3600"]
          env:
            - name: DB_USER
              valueFrom:
                secretKeyRef:
                  name: meu-secret
                  key: DB_USER
            - name: DB_PASS
              valueFrom:
                secretKeyRef:
                  name: meu-secret
                  key: DB_PASS

Aplique:

kubectl apply -f deployment-secret-env.yaml

Verifique:

kubectl logs -l app=secret-env

Você verá:

DB_USER=admin
DB_PASS=supersecreta

Montar Secrets como Arquivos

Criar novo Deployment montando o Secret Crie um arquivo deployment-secret-volume.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-com-secret-volume
spec:
  replicas: 1
  selector:
    matchLabels:
      app: secret-volume
  template:
    metadata:
      labels:
        app: secret-volume
    spec:
      containers:
        - name: busybox
          image: busybox
          command: ["sh", "-c", "cat /secrets/DB_USER && echo && cat /secrets/DB_PASS && echo && sleep 3600"]
          volumeMounts:
            - name: secret-volume
              mountPath: /secrets
              readOnly: true
      volumes:
        - name: secret-volume
          secret:
            secretName: meu-secret

Aplique:

kubectl apply -f deployment-secret-volume.yaml

Verifique os logs:

kubectl logs -l app=secret-volume

SideCar

Criar um Deployment com um container nginx e um sidecar php-fpm

Arquivo nginx-php-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-php-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-php
  template:
    metadata:
      labels:
        app: nginx-php
    spec:
      volumes:
        - name: app-volume
          emptyDir: {}
      containers:
        - name: nginx
          image: nginx:alpine
          ports:
            - containerPort: 80
          volumeMounts:
            - name: app-volume
              mountPath: /usr/share/nginx/html
          # Custom NGINX config to use PHP-FPM (opcional: pode montar um config aqui se quiser)
        - name: php
          image: php:8.1-fpm-alpine
          volumeMounts:
            - name: app-volume
              mountPath: /usr/share/nginx/html

Aplique o Deployment:

kubectl apply -f nginx-php-deployment.yaml

Após o Deployment estar no ar:

kubectl get pods -l app=nginx-php
# copie o nome do pod e rode:
kubectl exec -it <nome-do-pod> -c php -- sh -c 'echo "<?php phpinfo(); ?>" > /usr/share/nginx/html/index.php'

Expor via port-forward

kubectl port-forward deployment/nginx-php-deploy 8080:80

Acesse via navegador http://localhost:8080/index.php

Projeto

Crie um ConfigMap para manter as informações não sensíveis de banco de dados (usuário e banco). Configure o Deployment da aplicação e o StatefulSet do banco de dados para utilizar essas informações.

Crie um Secret para manter as senhas do banco de dados (senha de usuário e senha de root), e configure o Deployment da aplicação e o StatefulSet do banco de dados para utilizar essas senhas.

Crie um ConfigMap para manter o init_db.sql, e configure o StatefulSet do banco de dados para montar esse script na pasta /docker-entrypoint-initdb.d/.

Desafio

O que aconteceu?

Como configurar o nginx para enviar as requisições de páginas php para o PHP-FPM?

Dica: Configuração básica do nginx para prover php:

server {
  listen 80;
  server_name localhost;
  root /usr/share/nginx/html;
  index index.php index.html;
  location / {
    try_files $uri $uri/ /index.php$is_args$args;
  }
  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass <SERVIDOR>:9000;
    fastcgi_index index.php;
    include fastcgi.conf;
  }
}