├── .github └── workflows │ └── jekyll-gh-pages.yml ├── LICENSE ├── README.md └── docs ├── docker ├── day-1 │ └── README.md ├── day-2 │ ├── GLOSSARIO.md │ ├── README.md │ ├── SENHAS.md │ ├── TIMELINE.md │ └── files │ │ ├── apache │ │ ├── Dockerfile.v1 │ │ └── Dockerfile.v2 │ │ ├── multistage │ │ ├── Dockerfile.v1 │ │ ├── Dockerfile.v2 │ │ ├── Dockerfile.v3 │ │ ├── Dockerfile.v4 │ │ └── hello.go │ │ └── nginx │ │ ├── Dockerfile.v1 │ │ ├── Dockerfile.v2 │ │ ├── Dockerfile.v3 │ │ ├── Dockerfile.v4 │ │ └── index.html ├── day-3 │ ├── DISTROLESS.md │ ├── README.md │ ├── SCOUT.md │ └── files │ │ ├── Dockerfile │ │ └── docker-compose.yml ├── day-4 │ ├── README.md │ └── VOLUMES.md ├── day-5 │ └── README.md └── day-6 │ ├── README.md │ └── files │ └── docker-compose.yaml └── k8s ├── day-1 ├── README.md ├── TROUBLOUSHOOTING.yml └── files │ ├── kind.yml │ ├── kubernetes-ports.sh │ └── tools.sh ├── day-10 ├── README.md └── files │ ├── pod-monitor │ ├── nginx-pod-monitor.yaml │ └── nginx-pod.yaml │ ├── prometheus-rules │ └── nginx-prometheus-rule.yaml │ └── service-monitor │ ├── nginx-config.yml │ ├── nginx-deployment.yml │ ├── nginx-pod-monitor.yml │ ├── nginx-service-monitor.yml │ └── nginx-service.yml ├── day-11 ├── README.md └── files │ ├── app │ ├── app.yaml │ └── redis.yaml │ ├── ingress-1.yaml │ ├── ingress-2.yaml │ ├── ingress-3.yaml │ ├── ingress-4.yaml │ ├── ingress-5.yaml │ ├── ingress-6.yaml │ └── kind │ └── kind-config.yaml ├── day-2 ├── README.md └── files │ ├── deployment.yml │ ├── meu-pod-multicontainer.yml │ └── multicontainer-limitado.yml ├── day-3 ├── README.md └── files │ ├── deploy-recreate.yml │ ├── deploy-update.yml │ └── deploy.yml ├── day-4 ├── README.md └── files │ ├── daemonset.yml │ ├── deployment.yml │ ├── nginx-liveness.yml │ ├── nginx-readiness.yml │ ├── nginx-startup.yml │ └── replicaset.yml ├── day-5 ├── EXTRAS.MD └── README.md ├── day-6 ├── NFS.md ├── README.md └── files │ ├── delete.yaml │ ├── pv-nfs.yml │ ├── pvc-nfs.yml │ ├── recycle.yml │ └── retain.yml ├── day-7 ├── README.md └── files │ ├── nginx-clusterip.yml │ ├── nginx-headless-service.yaml │ ├── nginx-lb.yml │ ├── nginx-nodeport.yml │ └── nginx-statefulset.yaml ├── day-8 ├── README.md └── files │ ├── configmap.yml │ ├── nginx-pod.yml │ ├── nginx.conf │ └── secret.yml └── day-9 └── files └── README.md /.github/workflows/jekyll-gh-pages.yml: -------------------------------------------------------------------------------- 1 | # Sample workflow for building and deploying a Jekyll site to GitHub Pages 2 | name: Deploy Jekyll with GitHub Pages dependencies preinstalled 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ["main"] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 19 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 20 | concurrency: 21 | group: "pages" 22 | cancel-in-progress: false 23 | 24 | jobs: 25 | # Build job 26 | build: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v4 31 | - name: Setup Pages 32 | uses: actions/configure-pages@v4 33 | - name: Build with Jekyll 34 | uses: actions/jekyll-build-pages@v1 35 | with: 36 | source: ./ 37 | destination: ./_site 38 | - name: Upload artifact 39 | uses: actions/upload-pages-artifact@v3 40 | 41 | # Deployment job 42 | deploy: 43 | environment: 44 | name: github-pages 45 | url: ${{ steps.deployment.outputs.page_url }} 46 | runs-on: ubuntu-latest 47 | needs: build 48 | steps: 49 | - name: Deploy to GitHub Pages 50 | id: deployment 51 | uses: actions/deploy-pages@v4 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Programa Intensivo em Containers e Kubernetes da LINUXtips! 2 | 3 | ![k8s](https://tudosobrekubernetes.tech/assets/navigator-1.svg) 4 | 5 | 6 | 7 |

Oi 👋, Eu sou Natália Granato

8 | 9 | - 🔭 DevOps and Observability Specialist 10 | - ✍️ Sempre aprendendo sobre Cloud Native, Kubernetes e Observability. 11 | - 📫 Você pode me encontrar nas redes [Links](https://linktr.ee/nataliagranato). 12 | - 📫 Você pode entrar em contato pelo e-mail: **contato@nataliagranato.xyz** 13 | - 📄 Conheça as minhas experiências [linkedin](https://www.linkedin.com/in/nataliagranato). 14 | 15 | Acompanhe o meu progresso no PICK de 2024 nesse repositório. 16 | 17 | # Índice 18 | 19 | ## Angela Davis: 20 | 1. [Angela Davis](https://github.com/Tech-Preta/pick/tree/main/docs/day-1) 21 | - [Simulando o sistema de arquivos do Debian](https://github.com/Tech-Preta/pick/tree/main/docs/day-1#simulando-o-sistema-de-arquivos-do-debian) 22 | - [Funcionamento dos Containers com Unshare e Cgroups](https://github.com/Tech-Preta/pick/tree/main/docs/day-1#simulando-o-funcionamento-de-containers) 23 | - [Copy on Write ou simplesmente CoW](https://github.com/Tech-Preta/pick/tree/main/docs/day-1#copy-on-write-ou-simplesmente-cow) 24 | - [Instalando e começando a usar o Docker](https://github.com/Tech-Preta/pick/tree/main/docs/day-1#instalando-e-come%C3%A7ando-a-usar-o-docker) 25 | 26 | 27 | 28 | ## Carolina Maria de Jesus: 29 | 2. [Carolina Maria de Jesus](https://github.com/Tech-Preta/pick/tree/main/docs/day-2) 30 | - [Dockerfile e Imagens de Containers](https://github.com/Tech-Preta/pick/blob/main/docs/day-2/README.md#dockerfile-e-imagens-de-containers) 31 | - [Dockerfile Descomplicado](https://github.com/Tech-Preta/pick/blob/main/docs/day-2/README.md#dockerfile-descomplicado) 32 | - [Multi-stage Build](https://github.com/Tech-Preta/pick/blob/main/docs/day-2/README.md#multi-stage) 33 | - [Registry](https://github.com/Tech-Preta/pick/blob/main/docs/day-2/README.md#o-que-%C3%A9-um-registry) 34 | - [Glossário](https://github.com/Tech-Preta/pick/blob/main/docs/day-2/GLOSSARIO.md) 35 | - [Criação de uma imagem Docker](https://github.com/Tech-Preta/pick/blob/main/docs/day-2/TIMELINE.md) 36 | - [Dockerfiles de exemplo](https://github.com/Tech-Preta/pick/tree/main/docs/day-2/files) 37 | 38 | 39 | ## Lélia Gonzales: 40 | 3. [Lélia Gonzales](https://github.com/Tech-Preta/pick/tree/main/docs/day-3) 41 | - [Dockerizando uma aplicação em Python](https://github.com/Tech-Preta/pick/blob/main/docs/day-3/README.md#dockeriza%C3%A7%C3%A3o-do-projeto) 42 | - [Verificando as Camadas das Imagens](https://github.com/Tech-Preta/pick/blob/main/docs/day-3/README.md#verificando-as-camadas-das-imagens) 43 | - [A arte da redução de imagens e vulnerabilidades](https://github.com/Tech-Preta/pick/blob/main/docs/day-3/README.md#reduzir-vulnerabilidades) 44 | - [Imagens Distroless](https://github.com/Tech-Preta/pick/blob/main/docs/day-3/DISTROLESS.md) 45 | - [Análise de vulnerabilidades com o Trivy](https://github.com/Tech-Preta/pick/blob/main/docs/day-3/README.md#an%C3%A1lise-de-vulnerabilidades-com-o-trivy) 46 | - [Experimentando o Docker Scout](https://github.com/Tech-Preta/pick/blob/main/docs/day-3/README.md#experimentando-o-docker-scout) 47 | - [Assinando suas imagens com o Cosign](https://github.com/Tech-Preta/pick/blob/main/docs/day-3/README.md#assinando-suas-imagens-com-o-cosign) 48 | 49 | 50 | 51 | ### Projeto Prático 52 | - [Gerador de senhas](https://github.com/nataliagranato/giropops-senhas): este é um projeto de uma aplicação em Python que gera senhas aleatórias e utiliza o Redis como um banco de dados para armazenamento temporário das senhas geradas. Saiba como executar a aplicação localmente e dockerizar o projeto. 53 | -------------------------------------------------------------------------------- /docs/docker/day-1/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Simulando o sistema de arquivos do Debian 3 | 4 | O debootstrap é uma ferramenta que instala um sistema base Debian em um subdiretório de outro sistema já instalado. Ele não requer um CD de instalação, apenas acesso a um repositório Debian. Além disso, o debootstrap pode ser instalado e executado a partir de outro sistema operacional. Por exemplo, você pode usar o debootstrap para instalar o Debian em uma partição não utilizada de um sistema Gentoo em execução. 5 | 6 | ## Primeiro, instale o debootstrap 7 | 8 | ``` 9 | apt-get install debootstrap -y 10 | ``` 11 | 12 | ### Em seguida, execute o debootstrap 13 | 14 | ``` 15 | debootstrap stable /debian 16 | ``` 17 | 18 | O comando debootstrap stable /debian instala um sistema base Debian estável no diretório /debian do sistema atual. 19 | 20 | Ele faz isso baixando os pacotes necessários do repositório Debian e instalando-os no diretório especificado. *Este comando é útil para criar um ambiente chroot, ou para instalar o Debian em uma partição não utilizada de outro sistema*. 21 | 22 | ## Simulando o funcionamento de Containers 23 | 24 | 1. Para utilizar os namespaces, execute o seguinte comando: 25 | 26 | ``` 27 | unshare --mount --uts --ipc --net --map-root-user --pid --fork chroot /debian /bash 28 | ``` 29 | 30 | * `unshare`: Este comando cria novos espaços de nomes (namespaces), que são usados para isolar recursos do sistema1. 31 | 32 | * `--mount`: Cria um novo espaço de nomes de montagem. Isso significa que as alterações feitas no sistema de arquivos não afetarão o restante do sistema1. 33 | 34 | * `--uts`: Cria um novo espaço de nomes UTS, o que significa que alterações no hostname ou no nome de domínio não afetarão o restante do sistema1. 35 | 36 | * `--ipc`: Cria um novo espaço de nomes IPC, proporcionando ao processo um espaço de nomes independente para filas de mensagens POSIX e System V, conjuntos de semáforos e segmentos de memória compartilhada1. 37 | 38 | * `--net`: Cria um novo espaço de nomes de rede, fornecendo ao processo pilhas IPv4 e IPv6 independentes, tabelas de roteamento IP, regras de firewall, etc1. 39 | 40 | * `--map-root-user`: Mapeia o usuário atual para o usuário root dentro do novo espaço de nomes2. 41 | 42 | * `--pid`: Cria um novo espaço de nomes PID, o que significa que os processos filhos terão um conjunto distinto de mapeamentos PID para processo em relação ao seu pai. 43 | 44 | * `--fork`: Faz com que o unshare crie um novo processo filho. 45 | 46 | * `chroot /debian`: Altera a raiz do sistema de arquivos para o diretório /debian. 47 | 48 | * `/bash`: Executa o comando /bash dentro do novo ambiente isolado. 49 | 50 | Portanto, este comando é útil para criar um ambiente isolado para testes ou depuração, onde as alterações feitas não afetarão o sistema principal. 51 | 52 | 1. Monte o sistema de arquivos proc: 53 | 54 | ``` 55 | mount -t proc proc /proc 56 | ``` 57 | 58 | 1. Verifique os processos em execução: 59 | 60 | ``` 61 | ps -ef 62 | ``` 63 | 64 | Nesse momento, simulamos o funcionamento do container com os isolamentos. Com o ps -ef, vemos com clareza a execução de somente dois processos. 65 | 66 | 1. Monte os sistemas de arquivos sysfs e tmp: 67 | 68 | ``` 69 | mount -t sysfs none /sysfs 70 | 71 | mount -t tmp none /tmp 72 | ``` 73 | 74 | ### Cgroups - Grupos de controle 75 | 76 | O `cgroups` é um recurso do kernel do Linux que permite limitar, contabilizar e isolar o uso de recursos por grupos de tarefas (processos) em execução em um sistema. 77 | 78 | * `Limitar Recursos`: Você pode configurar um cgroup para limitar quanto de um determinado recurso (como memória ou CPU) um processo pode usar3. 79 | 80 | * `Contabilizar Recursos`: O cgroups permite monitorar o uso de recursos por processos1. 81 | 82 | * `Isolar Recursos`: O cgroups fornece isolamento de recursos, garantindo que os processos em um cgroup não sejam afetados pelo uso de recursos em outros cgroups1. 83 | 84 | **Os cgroups são um componente-chave dos containers porque geralmente há vários processos em execução em um container que precisam ser controlados juntos**. Portanto, o cgroups é extremamente importante para o ajuste de desempenho de um sistema Linux. 85 | 86 | 1. Instale as ferramentas de cgroup: 87 | 88 | sudo apt install cgroup-tools -y 89 | 90 | 2. Crie grupos de controle: 91 | 92 | ``` 93 | sudo cgcreate -g cpu,memory,blkio,devices,freezer:giropops 94 | ``` 95 | 96 | 3. Verifique se o grupo giropops tem controle sobre a CPU: 97 | 98 | ``` 99 | ls /sys/fs/cgroup/cpu/giropops 100 | ``` 101 | 102 | 4. Classifique os grupos: 103 | 104 | ``` 105 | sudo cgclassify -g cpu,memory,blkio,devices,freezer:giropops 106 | ``` 107 | 108 | 5. Limite os recursos do grupo: 109 | 110 | ``` 111 | sudo cgset -r cpu.cfs_quota_us=1000 giropops 112 | ``` 113 | 114 | ### Copy on Write ou simplesmente CoW 115 | 116 | É uma técnica fundamental usada em containers, como Docker, para otimizar o uso de armazenamento e desempenho. Funciona da seguinte forma: 117 | 118 | * `Eficiência de Armazenamento`: Quando você tem uma ou mais cópias dos mesmos dados, o CoW é uma técnica simples baseada em ponteiros para armazenamento eficiente. Em vez de copiar todos os bytes para um novo diretório (um processo demorado e que consome disco), o CoW cria apenas um conjunto de ponteiros no novo diretório - um ponteiro para cada arquivo. 119 | 120 | * `Desempenho de Cópia`: Todas as operações de leitura para os arquivos no novo diretório abrirão os mesmos bytes apontados no diretório original. Se um usuário deseja modificar um dos arquivos no novo diretório, uma cópia real de seus bytes é feita nesse momento antes de permitir que o usuário faça as edições. 121 | 122 | * `Modificação de Arquivos`: Quando um arquivo em uma camada somente leitura (não a camada superior) é modificado, o arquivo inteiro é primeiro copiado da camada somente leitura para a camada gravável antes que a alteração seja feita. **Isso é chamado de Copy on Write**. 123 | 124 | Essas características do CoW permitem que uma única imagem Docker seja usada de maneira eficiente por vários containers e também para iniciar novos containers rapidamente. 125 | 126 | ### Instalando e começando a usar o Docker 127 | 128 | 1. Execute o seguinte comando para instalar o Docker: 129 | 130 | ``` 131 | curl -fsSL | sh 132 | ``` 133 | 134 | 2. Execute o seu primeiro container: 135 | 136 | ``` 137 | docker container run hello-world 138 | ``` 139 | 140 | 3. Para algo mais ambicioso, você pode executar um container Ubuntu com: 141 | 142 | ``` 143 | docker run -it ubuntu bash 144 | ``` 145 | 146 | Os parâmetros -i e -t são usados para controlar a interação com o container: 147 | 148 | * `-i (ou --interactive)`: Este parâmetro mantém o STDIN aberto mesmo sem um console anexado, permitindo a interação com o container. 149 | 150 | * `-t (ou --tty)`: Este parâmetro aloca um pseudo-TTY ou terminal, que permite que você interaja com o container como se estivesse em um terminal de comando. 151 | Juntos, -it, permitem que você inicie um container e interaja com ele através de um terminal. 152 | 153 | 4. Liste todos os containers: 154 | 155 | ``` 156 | docker container ls -a 157 | ``` 158 | 159 | 5. Execute um container Centos: 160 | 161 | ``` 162 | docker container run -ti centos:7 163 | ``` 164 | 165 | Para sair do container sem matar seu entrypoint "o processo principal", utilize o ctrl e p+q ao mesmo tempo para que ele continue em execução. 166 | 167 | Para voltar novamente para o container, utilize o seguinte comando: 168 | 169 | ``` 170 | docker container attach 171 | ``` 172 | 173 | 6. Criando um container sem inicializá-lo: 174 | 175 | ``` 176 | docker container create -ti ubuntu 177 | ``` 178 | 179 | Para executar o container recem criado, basta utilizar o "docker container start [CONTAINER ID]". 180 | 181 | 7. Parando um Container sem Matá-lo 182 | 183 | ``` 184 | docker container stop [CONTAINER ID] 185 | ``` 186 | 187 | 8. Reinicie um container: 188 | 189 | ``` 190 | docker container restart [CONTAINER ID] 191 | ``` 192 | 193 | 9. Despause um container: 194 | 195 | ``` 196 | docker container unpause [CONTAINER ID] 197 | ``` 198 | 199 | 10. Veja as estatísticas de um container: 200 | 201 | ``` 202 | docker container stats [CONTAINER ID] 203 | ``` 204 | 205 | 11. Para exibir os logs de forma dinâmica, ou seja, conforme aparecem novas mensagens ele atualiza a saída no terminal, utilizamos a opção "-f": 206 | 207 | ``` 208 | docker container logs -f [CONTAINER ID] 209 | ``` 210 | 211 | 12. Quando removemos um container, a imagem que foi utilizada para a sua criação permanece no host; somente o container é apagado. 212 | 213 | ``` 214 | docker container rm [CONTAINER ID] 215 | ``` 216 | -------------------------------------------------------------------------------- /docs/docker/day-2/GLOSSARIO.md: -------------------------------------------------------------------------------- 1 | # Glossário de Dockerfile 2 | 3 | - ADD: Instrução utilizada no Dockerfile para copiar arquivos e diretórios para dentro do container. 4 | 5 | - CMD: Instrução utilizada no Dockerfile para especificar o comando padrão a ser executado quando o container for iniciado. 6 | 7 | - COPY: Instrução utilizada no Dockerfile para copiar arquivos e diretórios para dentro do container. 8 | 9 | - ENTRYPOINT: Instrução utilizada no Dockerfile para especificar o comando padrão a ser executado quando o container for iniciado, porém não pode ser substituído ao iniciar o container. 10 | 11 | - ENV: Instrução utilizada no Dockerfile para definir variáveis de ambiente que serão utilizadas durante a construção e execução do container. 12 | 13 | - EXPOSE: Instrução utilizada no Dockerfile para definir as portas em que o container irá escutar, permitindo a comunicação com outros containers ou com o host. 14 | 15 | - FROM: Instrução utilizada no Dockerfile para especificar a imagem base que será utilizada para construir o container. 16 | 17 | - LABEL: Instrução utilizada no Dockerfile para adicionar metadados à imagem, como informações do autor e descrição. 18 | 19 | - MAINTAINER: Instrução utilizada no Dockerfile para especificar o autor da imagem. 20 | 21 | - RUN: Instrução utilizada no Dockerfile para executar comandos durante a construção do container. 22 | 23 | - USER: Instrução utilizada no Dockerfile para especificar o usuário que será usado para executar os comandos dentro do container. 24 | 25 | - VOLUME: Instrução utilizada no Dockerfile para definir um ponto de montagem de volume, permitindo o compartilhamento de dados entre o host e o container. 26 | 27 | - WORKDIR: Instrução utilizada no Dockerfile para definir o diretório de trabalho dentro do container, onde os comandos serão executados. 28 | -------------------------------------------------------------------------------- /docs/docker/day-2/README.md: -------------------------------------------------------------------------------- 1 | # Dockerfile e Imagens de Containers 2 | 3 | ### Imagens de Container 4 | 5 | As imagens de container são pacotes leves, autônomos e executáveis que contêm todo o necessário para executar um software, incluindo o código, runtime, bibliotecas, variáveis de ambiente e configurações. Elas são utilizadas para criar e executar containers, que são instâncias em tempo de execução das imagens de container. As imagens de container são criadas a partir de um Dockerfile e são armazenadas em repositórios, como Docker Hub, para fácil distribuição e compartilhamento. 6 | 7 | ### Dockerfile 8 | 9 | Um Dockerfile é um arquivo de texto simples que contém uma lista de instruções usadas para construir uma imagem de container. Ele descreve os passos necessários para criar uma imagem específica. Cada instrução no Dockerfile adiciona uma nova camada à imagem, permitindo a reutilização de camadas existentes e otimizando o processo de construção. 10 | 11 | ### Exemplo de Dockerfile 12 | 13 | ``` 14 | # Este Dockerfile cria uma imagem baseada no Alpine Linux e instala o Nginx. 15 | # Ele expõe a porta 80 e inicia o servidor Nginx. 16 | 17 | FROM alpine:latest 18 | # A instrução FROM especifica a imagem base para a imagem Docker que está sendo construída. 19 | # Neste caso, utiliza a imagem do Alpine Linux como base. 20 | 21 | RUN apk update && apk add nginx 22 | # A instrução RUN executa um comando dentro da imagem Docker durante o processo de construção. 23 | # Neste caso, ela atualiza as listas de pacotes e instala o Nginx usando o gerenciador de pacotes apk. 24 | 25 | # Expõe a porta 80 para tráfego HTTP. 26 | EXPOSE 80 27 | 28 | # O comando CMD especifica o comando a ser executado quando o contêiner é iniciado. 29 | # Neste caso, inicia o servidor Nginx. 30 | CMD ["nginx", "-g", "daemon off;"] 31 | ``` 32 | 33 | ### Buildando uma imagem 34 | 35 | Para construir uma imagem a partir de um Dockerfile, utilize o comando docker build seguido do nome da imagem e da versão: 36 | 37 | ``` 38 | docker build -t pick:v1.0.0 . 39 | ``` 40 | 41 | ### Listando imagens 42 | 43 | Para listar todas as imagens disponíveis localmente, utilize o comando: 44 | 45 | ``` 46 | docker imagens 47 | ``` 48 | 49 | ### Iniciando o Container com a Imagem Recém Criada 50 | 51 | Para iniciar um container usando a imagem recém-criada, utilize o comando docker run. Este comando também permite especificar opções como mapeamento de portas e nome do container: 52 | 53 | ``` 54 | docker run -p 8080:80 -d --name meu_container pick:v1.1.1 55 | ``` 56 | 57 | ### Dockerfile Descomplicado 58 | 59 | ## Principais Instruções 60 | 61 | - ADD: Copia novos arquivos, diretórios, arquivos TAR ou arquivos remotos e os adiciona ao filesystem do container. 62 | - CMD: Executa um comando quando o container é iniciado. 63 | - LABEL: Adiciona metadados à imagem. 64 | - COPY: Copia novos arquivos e diretórios para o filesystem do container. 65 | - ENTRYPOINT: Configura um container para rodar um executável. 66 | - ENV: Informa variáveis de ambiente ao container. 67 | - EXPOSE: Informa qual porta o container estará ouvindo. 68 | - FROM: Indica qual imagem será utilizada como base. 69 | - MAINTAINER: Especifica o autor da imagem. 70 | - RUN: Executa qualquer comando em uma nova camada na imagem. 71 | - USER: Determina qual usuário será utilizado na imagem. 72 | - VOLUME: Permite a criação de um ponto de montagem no container. 73 | - WORKDIR: Responsável por mudar do diretório "/" para o especificado nele. 74 | 75 | ### Desafio técnico 76 | 77 | O Dockerfile abaixo cria uma imagem baseada no Alpine Linux e instala o Nginx: 78 | 79 | ``` 80 | # Este Dockerfile cria uma imagem baseada no Alpine Linux e instala o Nginx. 81 | # Ele expõe a porta 80 e inicia o servidor Nginx. 82 | 83 | FROM alpine:latest 84 | # A instrução FROM especifica a imagem base para a imagem Docker que está sendo construída. 85 | # Neste caso, utiliza a imagem do Alpine Linux como base. 86 | 87 | RUN apk update && apk add nginx 88 | # A instrução RUN executa um comando dentro da imagem Docker durante o processo de construção. 89 | # Neste caso, ela atualiza as listas de pacotes e instala o Nginx usando o gerenciador de pacotes apk. 90 | 91 | # Expõe a porta 80 para tráfego HTTP. 92 | EXPOSE 80 93 | 94 | # O comando CMD especifica o comando a ser executado quando o contêiner é iniciado. 95 | # Neste caso, inicia o servidor Nginx. 96 | CMD ["nginx", "-g", "daemon off;"] 97 | ``` 98 | 99 | Para construir a imagem Docker, utilize o comando **docker build -t giropops-web .**, e para executar o contêiner, utilize **docker run -p 80:80 --name giropops-web giropops-web**. 100 | 101 | # Multi-stage 102 | 103 | O multi-stage build é um recurso do Docker que permite otimizar a criação de imagens Docker, mantendo os Dockerfiles fáceis de ler e manter. 104 | 105 | Com o multi-stage build, você pode usar várias instruções FROM no seu Dockerfile. Cada instrução FROM pode usar uma base diferente e cada uma delas inicia uma nova etapa da construção1. Você pode copiar seletivamente artefatos de um estágio para outro, deixando para trás tudo o que você não quer na imagem final. 106 | 107 | Por exemplo, você pode ter um estágio de compilação para cada serviço, seguido por um estágio de empacotamento, garantindo que cada imagem contenha apenas os artefatos necessários para a execução do serviço. 108 | 109 | Aqui está um exemplo de um Dockerfile com dois estágios separados: um para construir um binário e outro onde o binário é copiado do primeiro estágio para o próximo. 110 | 111 | ``` 112 | # syntax=docker/dockerfile:1 113 | FROM golang:1.21 as build 114 | WORKDIR /src 115 | COPY < 35 | from flask.cli import main 36 | File "/usr/local/lib/python3.8/dist-packages/flask/__init__.py", line 7, in 37 | from .app import Flask as Flask 38 | File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 27, in 39 | from . import cli 40 | File "/usr/local/lib/python3.8/dist-packages/flask/cli.py", line 17, in 41 | from .helpers import get_debug_flag 42 | File "/usr/local/lib/python3.8/dist-packages/flask/helpers.py", line 14, in 43 | from werkzeug.urls import url_quote 44 | ImportError: cannot import name 'url_quote' from 'werkzeug.urls' (/usr/local/lib/python3.8/dist-packages/werkzeug/urls.py) 45 | ``` 46 | 47 | ``` 48 | pip install --upgrade Flask 49 | ``` 50 | 51 | Ainda assim foi necessário especificar uma versão fixa para o Werkzeug: No arquivo requirements.txt, adicionando uma versão específica para o Werkzeug, como Werkzeug==2.2.2. 52 | 53 | Isso garantirá que a versão correta do Werkzeug seja instalada e resolva o problema. 54 | 55 | 6. Instalando o Redis, uma dependência do projeto: 56 | 57 | ``` 58 | sudo apt-get install redis -y 59 | ``` 60 | 61 | 7. Iniciando o Redis: 62 | 63 | ``` 64 | systemctl start redis && systemctl status redis 65 | ``` 66 | 67 | 8. Instale todas as dependências do python: 68 | 69 | ``` 70 | pip install --no-cache-dir -r requirements.txt 71 | ``` 72 | 73 | 9. Criando uma variável de ambiente para que a aplicação encontre o Redis: 74 | 75 | ``` 76 | export REDIS_HOST=localhost 77 | ``` 78 | 79 | 10. Iniciando a aplicação: 80 | 81 | ``` 82 | flask run --host=0.0.0.0 83 | ``` 84 | -------------------------------------------------------------------------------- /docs/docker/day-2/TIMELINE.md: -------------------------------------------------------------------------------- 1 | # Timeline: Criação de uma Imagem Docker 2 | 3 | - **Criação do Dockerfile**: O primeiro passo na criação de uma imagem Docker é criar um arquivo chamado Dockerfile. Esse arquivo contém as instruções necessárias para construir a imagem, como a escolha da base, a instalação de dependências e a configuração do ambiente. 4 | 5 | - **Build da Imagem**: Após a criação do Dockerfile, é necessário executar o comando docker build para iniciar o processo de construção da imagem. Nesse momento, o Docker irá ler o arquivo Dockerfile e compilar a imagem conforme as instruções especificadas. 6 | 7 | - **Tag da Imagem**: Após a conclusão do build, é possível adicionar tags à imagem para facilitar sua identificação e versionamento. Por exemplo, podemos adicionar uma tag indicando a versão da aplicação ou o ambiente de destino. 8 | 9 | - **Push da Imagem**: Para disponibilizar a imagem em um repositório remoto, é necessário utilizar o comando docker push. Esse comando envia a imagem para um registro, como o Docker Hub ou um registro privado, permitindo que outras pessoas possam baixar e utilizar a imagem. 10 | 11 | - **Verificação de Vulnerabilidades**: É importante garantir a segurança da imagem antes de disponibilizá-la para uso. Para isso, podemos utilizar ferramentas de verificação de vulnerabilidades, como o Trivy. Essas ferramentas analisam a imagem em busca de componentes com falhas de segurança conhecidas. 12 | 13 | - **Assinatura com o Cosign**: Para adicionar uma camada extra de segurança, é possível assinar digitalmente a imagem utilizando o Cosign. Essa assinatura garante a integridade da imagem, permitindo que os usuários verifiquem a autenticidade e a procedência da mesma. 14 | 15 | Esses são os principais marcos na criação de uma imagem Docker, desde a criação do Dockerfile até a assinatura com o Cosign. Cada passo é essencial para garantir a qualidade, segurança e confiabilidade da imagem. 16 | -------------------------------------------------------------------------------- /docs/docker/day-2/files/apache/Dockerfile.v1: -------------------------------------------------------------------------------- 1 | # Este Dockerfile cria uma imagem de servidor web Apache baseada no Debian 10. 2 | 3 | FROM debian:10 4 | 5 | # Atualiza as listas de pacotes e instala o servidor web Apache 6 | RUN apt-get update && apt-get install -y apache2 && apt-get clean 7 | 8 | # Define as variáveis de ambiente para o Apache 9 | ENV APACHE_LOCK_DIR="/var/lock" 10 | ENV APACHE_PID_FILE="/var/run/apache2.pid" 11 | ENV APACHE_RUN_USER="www-data" 12 | ENV APACHE_RUN_GROUP="www-data" 13 | ENV APACHE_LOG_DIR="/var/log/apache2" 14 | 15 | # Define uma etiqueta para a imagem 16 | LABEL description="Servidor Web" 17 | 18 | # Monta o diretório /var/www/html/ como um volume 19 | VOLUME /var/www/html/ 20 | 21 | # Expose port 80 for incoming HTTP traffic 22 | EXPOSE 80 -------------------------------------------------------------------------------- /docs/docker/day-2/files/apache/Dockerfile.v2: -------------------------------------------------------------------------------- 1 | # Define a imagem base como Debian 10 2 | FROM debian:10 3 | 4 | # Atualiza os pacotes e instala o Apache 2 5 | RUN apt-get update && apt-get install -y apache2 && apt-get clean 6 | 7 | # Define as variáveis de ambiente para o Apache 8 | ENV APACHE_LOCK_DIR="/var/lock" 9 | ENV APACHE_PID_FILE="/var/run/apache2/apache2.pid" 10 | ENV APACHE_RUN_USER="www-data" 11 | ENV APACHE_RUN_DIR="/var/run/apache2" 12 | ENV APACHE_RUN_GROUP="www-data" 13 | ENV APACHE_LOG_DIR="/var/log/apache2" 14 | 15 | # Define a descrição da imagem 16 | LABEL description="Servidor web" 17 | 18 | # Define o volume para o diretório /var/www/html/ 19 | VOLUME /var/www/html/ 20 | 21 | # Expõe a porta 80 para acesso externo 22 | EXPOSE 80 23 | 24 | # Define o comando de entrada como "/usr/sbin/apachectl" 25 | ENTRYPOINT ["/usr/sbin/apachectl"] 26 | 27 | # Define os argumentos padrão para o comando de entrada 28 | CMD ["-D", "FOREGROUND"] 29 | -------------------------------------------------------------------------------- /docs/docker/day-2/files/multistage/Dockerfile.v1: -------------------------------------------------------------------------------- 1 | # Este Dockerfile configura uma compilação em várias etapas para uma aplicação Go. 2 | # Ele utiliza a imagem base golang:1.18, copia o código da aplicação para o contêiner, 3 | # inicializa o módulo Go, compila a aplicação e define o comando para executar o executável compilado. 4 | 5 | # Imagem base 6 | FROM golang:1.23rc2 7 | 8 | # Diretório de trabalho 9 | WORKDIR /app 10 | 11 | # Copia o código da aplicação para o contêiner 12 | COPY . ./ 13 | 14 | # Inicializa o módulo Go 15 | RUN go mod init hello 16 | 17 | # Compila a aplicação 18 | RUN go build -o /app/hello 19 | 20 | # Define o comando para executar o executável compilado 21 | CMD ["/app/hello"] 22 | -------------------------------------------------------------------------------- /docs/docker/day-2/files/multistage/Dockerfile.v2: -------------------------------------------------------------------------------- 1 | # Estágio de compilação 2 | FROM golang:1.18 as build 3 | 4 | # Define o diretório de trabalho como /app 5 | WORKDIR /app 6 | 7 | # Copia o conteúdo do diretório atual para o diretório de trabalho atual no contêiner 8 | COPY . ./ 9 | 10 | # O comando "go mod init" é usado para criar um novo arquivo go.mod no diretório de trabalho atual. 11 | RUN go mod init hello 12 | 13 | # O comando "go build" é usado para compilar o aplicativo Go e a flag "-o" é usada para especificar o local de saída do binário. 14 | # Neste caso, o binário será gerado em /app/hello. 15 | RUN go build -o /app/hello 16 | 17 | # Estágio de execução 18 | FROM alpine:3.19 19 | 20 | # Copia o arquivo binário 'hello' da etapa 'build' para o diretório '/app/hello' na imagem final. 21 | COPY --from=build /app/hello /app/hello 22 | 23 | # Especifica o comando a ser executado quando o contêiner é iniciado. 24 | CMD ["/app/hello"] -------------------------------------------------------------------------------- /docs/docker/day-2/files/multistage/Dockerfile.v3: -------------------------------------------------------------------------------- 1 | # Estágio de compilação 2 | FROM golang:1.18 as build 3 | 4 | # Define o diretório de trabalho como /app 5 | WORKDIR /app 6 | 7 | # Copia o conteúdo do diretório atual para o diretório de trabalho atual no contêiner 8 | COPY . ./ 9 | 10 | # O comando "go mod init" é usado para criar um novo arquivo go.mod no diretório de trabalho atual. 11 | RUN go mod init hello 12 | 13 | # O comando "go build" é usado para compilar o aplicativo Go e a flag "-o" é usada para especificar o local de saída do binário. 14 | # Neste caso, o binário será gerado em /app/hello. 15 | RUN go build -o /app/hello 16 | 17 | # Estágio de execução 18 | FROM alpine:3.19 19 | 20 | # Copia o arquivo binário 'hello' da etapa 'build' para o diretório '/app/hello' na imagem final. 21 | COPY --from=build /app/hello /app/hello 22 | 23 | # Define a variável de ambiente "app" como "hello_world" 24 | ENV APP="hello_world" 25 | 26 | # Define a variável de ambiente "PICK" como "nataliagranato" 27 | ARG PICK="nataliagranato" 28 | 29 | # Exibe o valor da variável de ambiente "PICK" 30 | ENV PICK=$PICK 31 | 32 | # Exibe o valor da variável de ambiente "PICK" 33 | RUN "echo "O alune do PICK é: $PICK" 34 | 35 | # Especifica o comando a ser executado quando o contêiner é iniciado. 36 | CMD ["/app/hello"] -------------------------------------------------------------------------------- /docs/docker/day-2/files/multistage/Dockerfile.v4: -------------------------------------------------------------------------------- 1 | # Estágio de compilação 2 | FROM golang:1.18 as build 3 | 4 | # Define o diretório de trabalho como /app 5 | WORKDIR /app 6 | 7 | # Copia o conteúdo do diretório atual para o diretório de trabalho atual no contêiner 8 | COPY . ./ 9 | 10 | # O comando "go mod init" é usado para criar um novo arquivo go.mod no diretório de trabalho atual. 11 | RUN go mod init hello 12 | 13 | # O comando "go build" é usado para compilar o aplicativo Go e a flag "-o" é usada para especificar o local de saída do binário. 14 | # Neste caso, o binário será gerado em /app/hello. 15 | RUN go build -o /app/hello 16 | 17 | # Estágio de execução 18 | FROM alpine:3.19 19 | 20 | # Substituindo o shell padrão pelo bash 21 | SHELL [ "/bin/bash" ] 22 | 23 | # Copia o arquivo binário 'hello' da etapa 'build' para o diretório '/app/hello' na imagem final. 24 | COPY --from=build /app/hello /app/hello 25 | 26 | # Define a variável de ambiente "app" como "hello_world" 27 | ENV APP="hello_world" 28 | 29 | # Define a variável de ambiente "PICK" como "nataliagranato" 30 | ARG PICK="nataliagranato" 31 | 32 | # Exibe o valor da variável de ambiente "PICK" 33 | ENV PICK=$PICK 34 | 35 | # Exibe o valor da variável de ambiente "PICK" 36 | RUN "echo "O alune do PICK é: $PICK" 37 | 38 | # Guarda os dados do container no volume /app/dados 39 | VOLUME /app/dados 40 | 41 | # Especifica o comando a ser executado quando o contêiner é iniciado. 42 | CMD ["/app/hello"] -------------------------------------------------------------------------------- /docs/docker/day-2/files/multistage/hello.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | 7 | fmt.Println("Programa Intensivo em Containers e Kubernetes") 8 | 9 | } -------------------------------------------------------------------------------- /docs/docker/day-2/files/nginx/Dockerfile.v1: -------------------------------------------------------------------------------- 1 | # Este Dockerfile cria uma imagem baseada no Ubuntu 18.04 e instala o Nginx. 2 | # Ele expõe a porta 80 e inicia o servidor Nginx. 3 | 4 | FROM ubuntu:18.04 5 | # A instrução FROM especifica a imagem base para a imagem Docker que está sendo construída. 6 | # Neste caso, utiliza a imagem do Ubuntu 18.04 como base. 7 | 8 | RUN apt-get update && apt-get install nginx -y 9 | # A instrução RUN executa um comando dentro da imagem Docker durante o processo de construção. 10 | # Neste caso, ela atualiza as listas de pacotes e instala o Nginx usando o gerenciador de pacotes apt-get. 11 | 12 | # Expõe a porta 80 para tráfego HTTP. 13 | EXPOSE 80 14 | 15 | # O comando CMD especifica o comando a ser executado quando o contêiner é iniciado. 16 | # Neste caso, inicia o servidor Nginx com a opção "daemon off;", que mantém o processo em execução em primeiro plano. 17 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /docs/docker/day-2/files/nginx/Dockerfile.v2: -------------------------------------------------------------------------------- 1 | # Este Dockerfile cria uma imagem baseada no Ubuntu 18.04 e instala o Nginx. 2 | # Ele expõe a porta 80 e inicia o servidor Nginx. 3 | 4 | FROM ubuntu:18.04 5 | # A instrução FROM especifica a imagem base para a imagem Docker que está sendo construída. 6 | # Neste caso, utiliza a imagem do Ubuntu 18.04 como base. 7 | 8 | # Instala o servidor web Nginx 9 | RUN apt-get update && apt-get install nginx -y && rm -rf /var/lib/apt/lists/* 10 | # Este comando Dockerfile instala o servidor web Nginx no contêiner. 11 | # Ele atualiza o sistema operacional e, em seguida, usa o comando apt-get para instalar o pacote nginx. 12 | # O parâmetro "-y" é usado para confirmar automaticamente todas as perguntas de instalação. 13 | # Por fim, o comando "rm -rf /var/lib/apt/lists/*" remove os arquivos de lista de pacotes desnecessários para economizar espaço em disco. 14 | 15 | # Expõe a porta 80 para tráfego HTTP. 16 | EXPOSE 80 17 | 18 | # Copia o arquivo index.html para o diretório /var/www/html/ dentro do container 19 | COPY index.html /var/www/html/ 20 | 21 | # Define o diretório de trabalho como /var/www/html/ dentro do container 22 | WORKDIR /var/www/html/ 23 | 24 | # O comando CMD especifica o comando a ser executado quando o contêiner é iniciado. 25 | # Neste caso, inicia o servidor Nginx com a opção "daemon off;", que mantém o processo em execução em primeiro plano. 26 | CMD ["nginx", "-g", "daemon off;"] 27 | 28 | # Define a variável de ambiente APP_VERSION com o valor 1.0.0. 29 | ENV APP_VERSION 1.0.0 30 | -------------------------------------------------------------------------------- /docs/docker/day-2/files/nginx/Dockerfile.v3: -------------------------------------------------------------------------------- 1 | # Este Dockerfile cria uma imagem baseada no Ubuntu 18.04 e instala o Nginx. 2 | # Ele expõe a porta 80 e inicia o servidor Nginx. 3 | 4 | FROM ubuntu:18.04 5 | # A instrução FROM especifica a imagem base para a imagem Docker que está sendo construída. 6 | # Neste caso, utiliza a imagem do Ubuntu 18.04 como base. 7 | 8 | LABEL maintainer="contato@nataliagranato.xyz" 9 | # A instrução LABEL adiciona metadados à imagem. 10 | 11 | # Instala o servidor web Nginx 12 | RUN apt-get update && apt-get install nginx -y && rm -rf /var/lib/apt/lists/* 13 | # Este comando Dockerfile instala o servidor web Nginx no contêiner. 14 | # Ele atualiza o sistema operacional e, em seguida, usa o comando apt-get para instalar o pacote nginx. 15 | # O parâmetro "-y" é usado para confirmar automaticamente todas as perguntas de instalação. 16 | # Por fim, o comando "rm -rf /var/lib/apt/lists/*" remove os arquivos de lista de pacotes desnecessários para economizar espaço em disco. 17 | 18 | # Expõe a porta 80 para tráfego HTTP. 19 | EXPOSE 80 20 | 21 | # Copia o arquivo index.html para o diretório /var/www/html/ dentro do container 22 | COPY index.html /var/www/html/ 23 | 24 | # Define o diretório de trabalho como /var/www/html/ dentro do container 25 | WORKDIR /var/www/html/ 26 | 27 | # Define a variável de ambiente APP_VERSION com o valor 1.0.0. 28 | ENV APP_VERSION 1.0.0 29 | 30 | ENTRYPOINT [ "nginx" ] 31 | # A instrução ENTRYPOINT permite que você configure um contêiner para executar um comando específico quando for iniciado. 32 | # É o processo principal do contêiner. Se este processo morrer, o contêiner também morre. 33 | 34 | CMD ["-g", "daemon off;"] 35 | # O comando CMD especifica o comando a ser executado quando o contêiner é iniciado. 36 | # Neste caso, inicia o servidor Nginx com a opção "daemon off;", que mantém o processo em execução em primeiro plano. 37 | # Usando o ENTRYPOINT e o CMD juntos, você pode definir o comando principal do contêiner e fornecer argumentos que podem ser substituídos quando o contêiner é iniciado. -------------------------------------------------------------------------------- /docs/docker/day-2/files/nginx/Dockerfile.v4: -------------------------------------------------------------------------------- 1 | # Este Dockerfile cria uma imagem baseada no Ubuntu 18.04 e instala o Nginx. 2 | # Ele expõe a porta 80 e inicia o servidor Nginx. 3 | 4 | FROM ubuntu:18.04 5 | # A instrução FROM especifica a imagem base para a imagem Docker que está sendo construída. 6 | # Neste caso, utiliza a imagem do Ubuntu 18.04 como base. 7 | 8 | LABEL maintainer="contato@nataliagranato.xyz" 9 | # A instrução LABEL adiciona metadados à imagem. 10 | 11 | # Instala o servidor web Nginx 12 | RUN apt-get update && apt-get install nginx curl -y && rm -rf /var/lib/apt/lists/* 13 | # Este comando Dockerfile instala o servidor web Nginx no contêiner. 14 | # Ele atualiza o sistema operacional e, em seguida, usa o comando apt-get para instalar o pacote nginx. 15 | # O parâmetro "-y" é usado para confirmar automaticamente todas as perguntas de instalação. 16 | # Por fim, o comando "rm -rf /var/lib/apt/lists/*" remove os arquivos de lista de pacotes desnecessários para economizar espaço em disco. 17 | 18 | # Expõe a porta 80 para tráfego HTTP. 19 | EXPOSE 80 20 | 21 | ADD https://github.com/helm/helm/archive/refs/tags/v3.14.3.tar.gz /root/ 22 | # A instrução ADD copia arquivos, diretórios e URLs para o sistema de arquivos do contêiner. 23 | 24 | # Copia o arquivo index.html para o diretório /var/www/html/ dentro do container 25 | COPY index.html /var/www/html/ 26 | 27 | # Define o diretório de trabalho como /var/www/html/ dentro do container 28 | WORKDIR /var/www/html/ 29 | 30 | # Define a variável de ambiente APP_VERSION com o valor 1.0.0. 31 | ENV APP_VERSION 1.0.0 32 | 33 | ENTRYPOINT [ "nginx" ] 34 | # A instrução ENTRYPOINT permite que você configure um contêiner para executar um comando específico quando for iniciado. 35 | # É o processo principal do contêiner. Se este processo morrer, o contêiner também morre. 36 | 37 | CMD ["-g", "daemon off;"] 38 | # O comando CMD especifica o comando a ser executado quando o contêiner é iniciado. 39 | # Neste caso, inicia o servidor Nginx com a opção "daemon off;", que mantém o processo em execução em primeiro plano. 40 | # Usando o ENTRYPOINT e o CMD juntos, você pode definir o comando principal do contêiner e fornecer argumentos que podem ser substituídos quando o contêiner é iniciado. 41 | 42 | HEALTHCHECK --timeout=15s CMD curl -f loscalhost || exit 1 43 | # A instrução HEALTHCHECK instrui o Docker a verificar a saúde do contêiner. 44 | # Neste caso, ele executa o comando "curl localhost" a cada 15 segundos. 45 | # Se o comando falhar, o contêiner será considerado não saudável e será reiniciado. -------------------------------------------------------------------------------- /docs/docker/day-2/files/nginx/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Programa Intensivo em Containers e Kubernetes da LINUXtips 6 | 7 | 8 | 9 |

Programa Intensivo em Containers e Kubernetes da LINUXtips!

10 | 11 |

Com o Programa Intensivo em Containers e Kubernetes da LINUXtips, voce tera acesso a uma formacao completa e 12 | totalmente pratica, que nao apenas transfere conhecimento, mas tambem prepara voce para enfrentar desafios reais 13 | no mundo real.

14 | 15 | 16 |

Confira o meu repositorio no GitHub: https://github.com/Tech-Preta/pick

18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/docker/day-3/DISTROLESS.md: -------------------------------------------------------------------------------- 1 | # A Arte da Minimização: Imagens Distroless 2 | 3 | ### Introdução 4 | 5 | No mundo dos containers, existe uma tendência emergente chamada "Distroless". Este termo é um neologismo que descreve uma imagem de container que contém apenas as dependências e artefatos necessários para a execução do aplicativo, eliminando a distribuição completa do sistema operacional. Neste capítulo, exploraremos o conceito de distroless, suas vantagens, desvantagens e como implementá-lo em seu próprio ambiente. 6 | 7 | ### O que é Distroless? 8 | 9 | "Distroless" refere-se à estratégia de construir imagens de containers que são efetivamente "sem distribuição". Isso significa que elas não contêm a distribuição típica de um sistema operacional Linux, como shell de linha de comando, utilitários ou bibliotecas desnecessárias. Ao invés disso, essas imagens contêm apenas o ambiente de runtime (como Node.js, Python, Java, etc.) e o aplicativo em si. 10 | 11 | ### Benefícios do Distroless 12 | 13 | O principal benefício das imagens Distroless é a segurança. Ao excluir componentes não necessários, o potencial de ataque é significativamente reduzido. Além disso, sem as partes extras do sistema operacional, o tamanho do container é minimizado, economizando espaço de armazenamento e aumentando a velocidade de deploy. 14 | 15 | ### Desafios do Distroless 16 | 17 | Apesar de seus benefícios, a estratégia Distroless não está isenta de desafios. Sem um shell ou utilitários de sistema operacional, a depuração pode ser mais complicada. Além disso, a construção de imagens Distroless pode ser um pouco mais complexa, pois requer uma compreensão cuidadosa das dependências do aplicativo. 18 | 19 | ### Implementando Distroless 20 | 21 | Existem várias maneiras de implementar uma estratégia Distroless. A mais simples é usar uma das imagens base Distroless fornecidas pelo Google e pela Chainguard. Estas imagens são projetadas para serem o mais minimalistas possível e podem ser usadas como ponto de partida para a construção de suas próprias imagens de container. 22 | 23 | ### Conclusão 24 | 25 | Distroless representa uma evolução na maneira como pensamos sobre imagens de containers. Ele nos força a questionar o que realmente precisamos em nosso ambiente de execução e nos encoraja a minimizar o excesso. Embora a implementação de uma estratégia Distroless possa ser um desafio, os benefícios em termos de segurança e eficiência tornam essa uma consideração valiosa para qualquer equipe de desenvolvimento. 26 | -------------------------------------------------------------------------------- /docs/docker/day-3/README.md: -------------------------------------------------------------------------------- 1 | # Dockerização do Projeto 2 | 3 | Para dockerizar o projeto, siga estas etapas: 4 | 5 | 1. **Construa a imagem docker**: 6 | 7 | ``` 8 | docker build -t nataliagranato/linuxtips-giropops-senhas:1.0 . 9 | ``` 10 | 11 | 2. **Inicie um contêiner Redis**: 12 | 13 | ``` 14 | docker container run -d -p 6000:6379 --name redis redis:alpine3.19 15 | ``` 16 | 17 | 3. **Descubra o IPAddress do Redis**: 18 | 19 | ``` 20 | docker inspect ID_REDIS | grep IPAddress 21 | ``` 22 | 23 | 4. **Executando a aplicação**: 24 | 25 | ``` 26 | docker run -d --name giropops-senhas -p 5000:5000 --env REDIS_HOST=IP_REDIS giropops-senhas:5.0 27 | ``` 28 | 29 | Ou 30 | 31 | 5. **Use o Docker Compose** para construir e iniciar os serviços: 32 | 33 | ``` 34 | docker-compose up -d 35 | ``` 36 | 37 | Isso iniciará tanto a aplicação quanto o contêiner Redis. A aplicação estará disponível em . 38 | 39 | **Certifique-se de que todas as portas necessárias estejam liberadas e de que não haja conflitos com outras aplicações em execução em sua máquina.** 40 | 41 | Observação: As versões dos pacotes e dependências podem variar. Certifique-se de usar as versões mais recentes e compatíveis com seu ambiente. 42 | 43 | 44 | # Verificando as Camadas das Imagens 45 | 46 | Para entender melhor as camadas de uma imagem Docker e suas implicações em termos de segurança e otimização, é possível usar o comando docker history. Esse comando fornece um histórico das camadas de uma imagem Docker, juntamente com informações sobre como cada camada foi criada. 47 | 48 | Por exemplo, para analisar o histórico da imagem nataliagranato/linuxtips-giropops-senhas:1.0, execute o seguinte comando: 49 | 50 | ``` 51 | docker history nataliagranato/linuxtips-giropops-senhas:1.0 52 | 53 | ``` 54 | 55 | Uma imagem com várias camadas e com um tamanho maior aumenta as chances de possuir maiores vulnerabilidades. 56 | 57 | Para diminuir as camadas das imagens e, consequentemente, reduzir as vulnerabilidades, algumas recomendações: 58 | 59 | 1. **Combine Comandos RUN**: 60 | - Agrupe comandos RUN em uma única instrução sempre que possível. Isso reduzirá o número de camadas criadas. Por exemplo: 61 | 62 | 63 | ``` 64 | # Ruim 65 | RUN apt-get update 66 | RUN apt-get install -y package1 67 | RUN apt-get install -y package2 68 | 69 | # Bom 70 | RUN apt-get update && \ 71 | apt-get install -y package1 package2 72 | 73 | ``` 74 | 75 | 76 | 2. **Remova Pacotes Temporários**: Limpe pacotes temporários após a instalação para evitar que eles permaneçam nas camadas da imagem. Por exemplo: 77 | 78 | 79 | ``` 80 | RUN apt-get install -y package1 package2 \ 81 | && apt-get clean \ 82 | && rm -rf /var/lib/apt/lists/* 83 | ``` 84 | 85 | 3. **Use Multi-Stage Builds**: Utilize multi-stage builds para compilar e construir aplicações em uma etapa e, em seguida, copiar apenas os artefatos necessários para a imagem final. Isso ajuda a manter a imagem final limpa e reduzir seu tamanho. Por exemplo: 86 | 87 | ``` 88 | # Stage 1: Compilação do aplicativo Go 89 | FROM golang:1.17 AS builder 90 | 91 | WORKDIR /app 92 | 93 | # Copia o código-fonte para o contêiner 94 | COPY . . 95 | 96 | # Compila o aplicativo Go 97 | RUN go build -o myapp . 98 | 99 | # Stage 2: Imagem final 100 | FROM debian:buster-slim 101 | 102 | WORKDIR /app 103 | 104 | # Copia o executável do estágio de compilação para a imagem final 105 | COPY --from=builder /app/myapp . 106 | 107 | # Define o comando padrão para executar o aplicativo quando o contêiner for iniciado 108 | CMD ["./myapp"] 109 | ``` 110 | 111 | A partir disso, temos uma melhoria na construção das nossas aplicações, mas também precisamos nos atentar para o aspecto da segurança, para isso temos diversos utilitários que podem nos ajudar nesse caminho. 112 | 113 | 114 | ## Reduzir Vulnerabilidades 115 | 116 | A segurança é uma preocupação fundamental ao lidar com imagens Docker. Aqui estão algumas práticas recomendadas para reduzir vulnerabilidades: 117 | 118 | ### 1. Atualize Regularmente 119 | 120 | Mantenha suas imagens Docker atualizadas aplicando patches e atualizações de segurança regularmente. Isso garante que as últimas correções de segurança estejam presentes na imagem. 121 | 122 | ### 2. Minimize Pacotes Instalados 123 | 124 | Instale apenas os pacotes necessários na imagem. Quanto menos software estiver presente, menor será a superfície de ataque e menos vulnerabilidades potenciais estarão presentes na imagem. 125 | 126 | ### 3. Use Imagens Oficiais e Confiáveis 127 | 128 | Utilize imagens oficiais e confiáveis do Docker Hub ou de repositórios verificados para garantir que as imagens base sejam mantidas e atualizadas regularmente. 129 | 130 | ### 4. Varredura de Vulnerabilidades 131 | 132 | Utilize ferramentas de varredura de vulnerabilidades, como o Trivy ou o Clair, para identificar e corrigir vulnerabilidades conhecidas nas imagens Docker. 133 | 134 | ### 5. Monitoramento Contínuo 135 | 136 | Implemente um processo de monitoramento contínuo para suas imagens Docker, verificando regularmente as vulnerabilidades e aplicando correções conforme necessário. 137 | 138 | Ao seguir essas práticas recomendadas, você poderá reduzir o risco de vulnerabilidades em suas imagens Docker, garantindo a segurança e confiabilidade de suas aplicações em contêineres. 139 | 140 | 141 | 142 | ### Análise de vulnerabilidades com o Trivy 143 | 144 | Para verificar vulnerabilidades na sua imagem, use o comando abaixo: 145 | 146 | ``` 147 | trivy image nataliagranato/linuxtips-giropops-senhas:2.0 148 | ``` 149 | 150 | Este comando fornecerá uma análise detalhada das vulnerabilidades presentes na imagem, permitindo que você conheça as vulnerabilidades, saiba como corrigir e etc. 151 | 152 | - O exemplo de saída desse comando, pode ser consultado aqui: https://github.com/nataliagranato/giropops-senhas/blob/develop/vulnerabilidades.txt 153 | 154 | 155 | #### Informações Iniciais: 156 | - O `trivy` informa que a varredura de vulnerabilidades está ativada, assim como a verificação de segredos. 157 | - Ele fornece uma dica sobre como desativar a verificação de segredos caso a varredura esteja lenta. 158 | 159 | #### Detecção do Sistema Operacional: 160 | - O `trivy` detecta o sistema operacional utilizado na imagem Docker, que no caso é Debian. 161 | 162 | #### Varredura de Vulnerabilidades: 163 | - O `trivy` inicia a varredura de vulnerabilidades específicas para o sistema operacional Debian. 164 | - Ele mostra o número total de arquivos específicos da linguagem (como arquivos Python no caso da imagem) que foram analisados. 165 | 166 | #### Lista de Vulnerabilidades: 167 | - A lista mostra cada biblioteca ou componente da imagem com suas vulnerabilidades associadas. 168 | - Cada entrada inclui detalhes como o nome da biblioteca, a vulnerabilidade, a gravidade, o status (por exemplo, se está afetado ou se há uma correção disponível), a versão instalada, a versão corrigida (se houver), e um título resumindo a vulnerabilidade. 169 | 170 | ### Como Corrigir as Vulnerabilidades Usando o Trivy: 171 | 172 | 1. **Atualize as Bibliotecas/Componentes**: 173 | - Identifique as bibliotecas/componentes listados com vulnerabilidades. 174 | - Para cada biblioteca, verifique se há uma versão corrigida disponível. 175 | - Atualize as bibliotecas/componentes para versões que corrijam as vulnerabilidades listadas. 176 | 177 | 2. **Reconstrua a Imagem Docker**: 178 | - Depois de atualizar as bibliotecas/componentes, reconstrua a imagem Docker utilizando a nova versão das bibliotecas/componentes. 179 | - Certifique-se de atualizar o arquivo Dockerfile ou o processo de construção conforme necessário. 180 | 181 | 3. **Refaça a Varredura de Vulnerabilidades**: 182 | - Após reconstruir a imagem Docker com as atualizações, execute novamente o `trivy` para verificar se as vulnerabilidades foram corrigidas. 183 | - Certifique-se de que todas as vulnerabilidades listadas anteriormente tenham sido resolvidas. 184 | 185 | 4. **Mantenha o Processo Regularmente**: 186 | - A varredura e correção de vulnerabilidades devem ser um processo regular durante o ciclo de vida do aplicativo. 187 | - Configure processos automatizados para realizar varreduras de vulnerabilidades regularmente e para aplicar atualizações conforme necessário. 188 | 189 | 190 | ### Experimentando o Docker Scout: 191 | 192 | - Faça a sua autenticação com `docker login` e utilize o comando abaixo para conhecer as CVEs, ou Common Vulnerabilities and Exposures, identificadores únicos atribuídos a vulnerabilidades de segurança específicas em software ou hardware. 193 | 194 | ``` 195 | docker scout cves nataliagranato/linuxtips-giropops-senhas:3.0 196 | ``` 197 | 198 | 199 | A saída será semelhante a isso: 200 | 201 | ``` 202 | i New version 1.6.0 available (installed version is 1.3.0) at https://github.com/docker/scout-cli 203 | ✓ Image stored for indexing 204 | ✓ Indexed 65 packages 205 | ✗ Detected 1 vulnerable package with 2 vulnerabilities 206 | 207 | 208 | ## Overview 209 | 210 | │ Analyzed Image 211 | ────────────────────┼───────────────────────────────────────────────── 212 | Target │ nataliagranato/linuxtips-giropops-senhas:3.0 213 | digest │ e37d53bc7930 214 | platform │ linux/amd64 215 | vulnerabilities │ 0C 1H 1M 0L 216 | size │ 30 MB 217 | packages │ 65 218 | 219 | 220 | ## Packages and Vulnerabilities 221 | 222 | 0C 1H 1M 0L redis 4.5.4 223 | pkg:pypi/redis@4.5.4 224 | 225 | ✗ HIGH CVE-2023-31655 226 | https://scout.docker.com/v/CVE-2023-31655?s=pypa&n=redis&t=pypi&vr=%3D4.5.4 227 | Affected range : =4.5.4 228 | Fixed version : not fixed 229 | 230 | ✗ MEDIUM CVE-2023-28859 231 | https://scout.docker.com/v/CVE-2023-28859?s=pypa&n=redis&t=pypi&vr=%3C5.0.0b1 232 | Affected range : <5.0.0b1 233 | Fixed version : 5.0.0b1 234 | 235 | 236 | 237 | 2 vulnerabilities found in 1 package 238 | LOW 0 239 | MEDIUM 1 240 | HIGH 1 241 | CRITICAL 0 242 | 243 | 244 | What's Next? 245 | View base image update recommendations → docker scout recommendations nataliagranato/linuxtips-giropops-senhas:3.0 246 | 247 | ``` 248 | 249 | Para ver as recomendações do Docker Scout utilize: 250 | 251 | ``` 252 | docker scout recommendations nataliagranato/linuxtips-giropops-senhas:3.0 253 | ``` 254 | 255 | 256 | ### Assinando suas imagens com o Cosign 257 | 258 | O Cosign facilita a assinatura das imagens de container, que atesta que aquela imagem realmente foi construída por você, adicionando uma assinatura digital usando uma chave privada para garantir a integridade e a proveniência da imagem. 259 | 260 | Agora vamos assinar uma imagem e publicar no Docker Hub, o registry público do Docker. 261 | 262 | 1. **Gerando o certificado e o par de chaves**: 263 | 264 | ``` 265 | cosign generate-key-pair 266 | ``` 267 | 268 | 2. **Assinando a nossa imagem**: 269 | 270 | ``` 271 | cosign sign --key cosign.key nataliagranato/linuxtips-giropops-senhas:e0942c7-20240319161939 272 | ``` 273 | 274 | - Será solicitado a senha da chave privada que você criou, insira a senha, depois disso você será perguntado se deseja enviar ao repositório remoto. 275 | 276 | 277 | Você verá uma saída semelhante a: 278 | 279 | ``` 280 | Enter password for private key: 281 | WARNING: Image reference nataliagranato/linuxtips-giropops-senhas:e0942c7-20240319161939 uses a tag, not a digest, to identify the image to sign. 282 | This can lead you to sign a different image than the intended one. Please use a 283 | digest (example.com/ubuntu@sha256:abc123...) rather than tag 284 | (example.com/ubuntu:latest) for the input to cosign. The ability to refer to 285 | images by tag will be removed in a future release. 286 | 287 | 288 | The sigstore service, hosted by sigstore a Series of LF Projects, LLC, is provided pursuant to the Hosted Project Tools Terms of Use, available at https://lfprojects.org/policies/hosted-project-tools-terms-of-use/. 289 | Note that if your submission includes personal data associated with this signed artifact, it will be part of an immutable record. 290 | This may include the email address associated with the account with which you authenticate your contractual Agreement. 291 | This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later, and is subject to the Immutable Record notice at https://lfprojects.org/policies/hosted-project-tools-immutable-records/. 292 | 293 | By typing 'y', you attest that (1) you are not submitting the personal data of any other person; and (2) you understand and agree to the statement and the Agreement terms at the URLs listed above. 294 | Are you sure you would like to continue? [y/N] y 295 | tlog entry created with index: 79606777 296 | Pushing signature to: index.docker.io/nataliagranato/linuxtips-giropops-senhas 297 | ``` 298 | 299 | 300 | 3. **Verificando a autenticidade de uma imagem**: 301 | 302 | - Você deve trocar a key para o par de chave pública gerado com a sua chave privada. 303 | 304 | ``` 305 | cosign verify --key cosign.pub nataliagranato/linuxtips-giropops-senhas:e0942c7-20240319161939 306 | ``` 307 | 308 | A saída será semelhante a: 309 | 310 | ``` 311 | Verification for index.docker.io/nataliagranato/linuxtips-giropops-senhas:e0942c7-20240319161939 -- 312 | The following checks were performed on each of these signatures: 313 | - The cosign claims were validated 314 | - Existence of the claims in the transparency log was verified offline 315 | - The signatures were verified against the specified public key 316 | 317 | [{"critical":{"identity":{"docker-reference":"index.docker.io/nataliagranato/linuxtips-giropops-senhas"},"image":{"docker-manifest-digest":"sha256:8bb7196e06cfa5e58e1a686584d7a972bd1a371b66309b7452976ef1bd2bbaf5"},"type":"cosign container image signature"},"optional":{"Bundle":{"SignedEntryTimestamp":"MEUCIQCWtamqxtW2029TmBmmUNOUplkhenX1A+7SMimyeKNdiwIgGPM3GzRwi9dCWufRqQlXth318GWWUM4kBLoK6N/KuJ4=","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI3YmEwYjhiOWY3MTcyNjJjM2IzMWI1NjQzYTZmYjhhMTU0MjI3MWVlZTQ5NTRiYzc0NzU0NmNjYjI4Yjk0ZDUyIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUURNTit5VUtGYk5PQWxsNUFpSExNWmNSekYvcWZxekp5eEZCaUJqOUU2NnFRSWdLWFlWSDhZelEvbUZvdytFUVRHaTZpNlBQWkh0UDk1NlVJa3QvS3RpcUJjPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVacmQwVjNXVWhMYjFwSmVtb3dRMEZSV1VsTGIxcEplbW93UkVGUlkwUlJaMEZGVDBRcmRIcGFUR3RSTkdKT2JXaDRkblpzTlRSM1psVlNWMjB6TmdveFVYSjRVVEZRU0hCbVZEaDBUbkF3ZGpsdk4zWTJNVFF2ZFZFeFJGTllUM0pZZFVWUE1GRXZXRzVXYUdkVU9HcDFabXBqV2sxck5WaEJQVDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHRDZz09In19fX0=","integratedTime":1710889924,"logIndex":79607170,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}}}}] 318 | ``` -------------------------------------------------------------------------------- /docs/docker/day-3/SCOUT.md: -------------------------------------------------------------------------------- 1 | # Docker Scout 2 | 3 | À medida que o desenvolvimento de software se torna cada vez mais orientado para containers, a segurança desses containers e das imagens usadas para criá-los ganha importância crítica. As imagens de container são construídas a partir de camadas de outras imagens e pacotes de software. Infelizmente, essas camadas e pacotes podem conter vulnerabilidades que tornam os containers e os aplicativos que eles executam vulneráveis a ataques. Aqui é onde o Docker Scout entra em cena. 4 | 5 | ## O que é o Docker Scout? 6 | 7 | O Docker Scout é uma ferramenta de análise de imagens avançada oferecida pelo Docker. Ele foi projetado para ajudar desenvolvedores e equipes de operações a identificar e corrigir vulnerabilidades em suas imagens de containers. Ao analisar suas imagens, o Docker Scout cria um inventário completo dos pacotes e camadas, também conhecido como Software Bill of Materials (SBOM). Este inventário é então correlacionado com um banco de dados de vulnerabilidades atualizado continuamente para identificar possíveis problemas de segurança. 8 | 9 | ## Como o Docker Scout funciona? 10 | 11 | Você pode usar o Docker Scout de várias maneiras. Ele é integrado ao Docker Desktop e ao Docker Hub, facilitando a análise de imagens durante o processo de construção e implantação. Além disso, ele também pode ser usado em um pipeline de integração contínua, através da interface de linha de comando (CLI) do Docker e no Docker Scout Dashboard. 12 | 13 | Para aqueles que hospedam suas imagens no JFrog Artifactory, o Docker Scout também oferece suporte à análise de imagens nesse ambiente. 14 | 15 | No CLI do Docker, o Docker Scout oferece vários comandos, incluindo `compare` para comparar duas imagens, `cves` para exibir as vulnerabilidades conhecidas como CVEs identificadas em um artefato de software, `quickview` para uma visão geral rápida de uma imagem e `recommendations` para exibir atualizações de imagens base disponíveis e recomendações de correção. 16 | 17 | ## Usando o Docker Scout 18 | 19 | O comando `docker scout cves` é especialmente importante, pois permite analisar um artefato de software em busca de vulnerabilidades. Este comando suporta a análise de imagens, diretórios OCI layout e arquivos tarball, como os criados pelo comando `docker save`. Isso dá aos desenvolvedores a flexibilidade de verificar a segurança de suas imagens de container de várias maneiras. 20 | 21 | ## Por que o Docker Scout é importante? 22 | 23 | O Docker Scout é uma ferramenta valiosa para melhorar a segurança dos containers. Ao identificar proativamente as vulnerabilidades e fornecer correções recomendadas, ajuda as equipes de desenvolvimento a fortalecer suas imagens de containers e, por sua vez, os aplicativos que estão sendo executados nesses containers. Em um mundo onde a segurança do software é fundamental, o Docker Scout é uma ferramenta indispensável para qualquer equipe de desenvolvimento orientada a containers. 24 | -------------------------------------------------------------------------------- /docs/docker/day-3/files/Dockerfile: -------------------------------------------------------------------------------- 1 | # Etapa de construção 2 | FROM cgr.dev/chainguard/python:latest-dev@sha256:5727408976bf17a1f034ead1bb6f9c145b392e3ffb4246c7e557680dc345f6ff as build 3 | 4 | # Definir o diretório de trabalho 5 | WORKDIR /app 6 | 7 | # Copiar arquivos para o diretório de trabalho 8 | COPY . /app 9 | 10 | # Instalar dependências 11 | RUN pip install -r requirements.txt --user 12 | 13 | # Etapa final 14 | FROM cgr.dev/chainguard/python:latest@sha256:a66be254adc25216a93a381b868d8ca68c0b56f489cd9c0d50d9707b49a8a0a4 15 | 16 | # Definir o diretório de trabalho 17 | WORKDIR /app 18 | 19 | COPY --from=build /home/nonroot/.local/lib/python3.12/site-packages /home/nonroot/.local/lib/python3.12/site-packages 20 | 21 | # Copiar o diretório de trabalho da etapa de construção para o diretório de trabalho da etapa final 22 | COPY --from=build /app /app 23 | 24 | # Definir o comando padrão do contêiner 25 | ENTRYPOINT ["python", "-m", "flask", "run", "--host=0.0.0.0"] -------------------------------------------------------------------------------- /docs/docker/day-3/files/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | giropops-senhas: 5 | image: nataliagranato/linuxtips-giropops-senhas:29a45f6-20240319160431 6 | build: . 7 | ports: 8 | - "5000:5000" 9 | environment: 10 | - REDIS_HOST=redis 11 | depends_on: 12 | - redis 13 | 14 | redis: 15 | container_name: redis 16 | image: redis:alpine3.19 17 | 18 | networks: 19 | giropops-senhas: 20 | driver: bridge -------------------------------------------------------------------------------- /docs/docker/day-4/README.md: -------------------------------------------------------------------------------- 1 | # O que são volumes e seus tipos 2 | 3 | Volumes no Docker são um componente crucial do ecossistema que armazena e gerencia dados persistentes gerados por contêineres efêmeros. Eles permitem que os dados persistam mesmo após a remoção ou atualização de um contêiner, evitando que dados essenciais do aplicativo sejam perdidos durante operações de rotinas. 4 | 5 | - Bind-mounts: São montagens de diretório do sistema host para um contêiner. Você precisa vincular as montagens de associação a um diretório específico no sistema host. 6 | 7 | - Volume-volume: São volumes criados e gerenciados pelo Docker 8 | 9 | - tmpfs: O tmpfs é um sistema de arquivos baseado em memória que permite armazenar dados de forma temporária na memória RAM. No Docker, quando você cria um contêiner com uma montagem tmpfs, o contêiner pode criar arquivos fora da camada gravável do contêiner. Ao contrário dos volumes e das montagens de associação, uma montagem tmpfs é temporária e persiste apenas na memória do host. Quando o contêiner para, a montagem tmpfs é removida e os arquivos escritos lá não serão persistidos. **Isso é útil para armazenar temporariamente arquivos sensíveis que você não deseja persistir** nem na camada gravável do host nem do contêiner. 10 | 11 | ## Criando um volume do tipo bind 12 | 13 | Para criar um volume do tipo bind, siga estes passos: 14 | 15 | 1. Crie um diretório na máquina hospedeira onde você deseja armazenar o volume. Neste exemplo, o diretório é criado usando o comando `sudo mkdir /volume`. 16 | 17 | 2. Execute um container Docker com a flag `--mount` para especificar o tipo de volume como `bind`. O parâmetro `src` especifica o caminho do diretório na máquina hospedeira, e o parâmetro `dst` especifica o caminho do diretório dentro do container. Neste exemplo, o comando é `docker container run -ti --mount type=bind,src=/volume,dst=/volume ubuntu`. 18 | 19 | ## Criando e gerenciando um volume do tipo volume 20 | 21 | 1. Listando os volumes: `docker volume ls`. 22 | 23 | 2. Criando um volume: `docker volume create giropops`. 24 | 25 | 3. Removendo um volume: `docker volume rm giropops`. 26 | 27 | 4. Obtendo detalhes do volume: `docker volume inspect giropops`. 28 | 29 | 5. Localizando o diretório dos volumes: `cd /var/lib/docker/volumes/`. 30 | 31 | 6. Removendo volumes não-utilizados: `docker volume prune`. 32 | 33 | 7. Montando um volume criado em algum container: `docker container run -d --mount type=volume,source=giropops,destination=/var/opa nginx`. 34 | 35 | 8. Containers utilizando o mesmo volume: `docker run -d --name testando-volumes-1 --mount type=volume,source=giropops,target=/giropops debian`. 36 | 37 | 9. Localizando volumes: `docker volume inspect --format '{{ .Mountpoint }}' giropops`. 38 | 39 | ## Outras formas de montar volumes e storage drivers 40 | 41 | Os drivers de armazenamento no Docker controlam como as imagens e os contêineres são armazenados e gerenciados no seu host Docker. O Docker suporta vários drivers de armazenamento, usando uma arquitetura plugável. Aqui estão alguns dos drivers de armazenamento disponíveis: 42 | 43 | 1. **overlay2**: É o driver de armazenamento preferido para todas as distribuições Linux atualmente suportadas e não requer nenhuma configuração extra. 44 | 45 | 2. **fuse-overlayfs**: É preferido apenas para a execução do Docker sem raiz em um host que não oferece suporte para overlay2 sem raiz. 46 | 47 | 3. **btrfs e zfs**: Esses drivers de armazenamento permitem opções avançadas, como a criação de “snapshots”, mas requerem mais manutenção e configuração. 48 | 49 | 4. **vfs**: O driver de armazenamento vfs é destinado a fins de teste e para situações em que nenhum sistema de arquivos com cópia na gravação pode ser usado. 50 | 51 | 5. **aufs**: Era o driver preferido para versões anteriores do Docker, quando executado em uma versão anterior do Ubuntu. 52 | 53 | 6. **devicemapper**: Requer direct-lvm. 54 | 55 | Cada driver de armazenamento tem suas próprias vantagens e desvantagens, e a escolha do driver de armazenamento a ser usado depende das necessidades específicas do seu aplicativo. 56 | 57 | ## Criando um volume do tipo tmpfs 58 | 59 | ``` 60 | docker container run -d --mount type=tmpfs,target=/strigus -p 8081:80 nginx 61 | ``` 62 | 63 | Este comando executa um contêiner Docker com a imagem do Nginx e configura um volume temporário (tmpfs) montado no diretório "/strigus". O contêiner é executado em segundo plano (-d) e expõe a porta 8081 do host para a porta 80 do contêiner (-p 8081:80). 64 | 65 | ### Volume Temporário (tmpfs) 66 | 67 | O volume temporário (tmpfs) é um tipo de volume no Docker que é armazenado na memória RAM em vez de ser armazenado no disco. Ele é útil para armazenar dados temporários que não precisam ser persistentes entre as reinicializações do contêiner. 68 | 69 | Ao usar um volume temporário, os dados são gravados diretamente na memória RAM, o que proporciona um acesso mais rápido aos dados. No entanto, é importante ter em mente que os dados armazenados em um volume temporário serão perdidos quando o contêiner for reiniciado ou desligado. 70 | 71 | No exemplo acima, o volume temporário é montado no diretório "/strigus" dentro do contêiner. Qualquer dado gravado nesse diretório será armazenado na memória RAM e será perdido quando o contêiner for reiniciado ou desligado. 72 | 73 | Para mais informações sobre volumes no Docker, consulte a documentação oficial: [Docker Volumes](https://docs.docker.com/storage/volumes/) 74 | -------------------------------------------------------------------------------- /docs/docker/day-4/VOLUMES.md: -------------------------------------------------------------------------------- 1 | 2 | # Introdução a volumes no Docker 3 | 4 | Bom, volumes nada mais são que diretórios externos ao container, que são montados diretamente nele, e dessa forma `bypassam` seu `filesystem`, ou seja, não seguem aquele padrão de camadas que falamos. Decepcionei você? Que bom, sinal de que é bem simples e você não vai ter problemas para entender. :) 5 | 6 | A principal função do volume é persistir os dados. Diferentemente do `filesystem` do container, que é volátil e toda informação escrita nele é perdida quando o container morre, quando você escreve em um volume aquele dado continua lá, independentemente do estado do container. 7 | 8 | Existem algumas particularidades entre os volumes e containers que valem a pena ser mencionadas: 9 | 10 | - O volume é inicializado quando o container é criado. 11 | 12 | - Caso ocorra de já haver dados no diretório em que você está montando como volume, ou seja, se o diretório já existe e está "populado" na imagem base, aqueles dados serão copiados para o volume. 13 | 14 | - Um volume pode ser reusado e compartilhado entre containers. 15 | 16 | - Alterações em um volume são feitas diretamente no volume. 17 | 18 | - Alterações em um volume não irão com a imagem quando você fizer uma cópia ou snapshot de um container. 19 | 20 | - Volumes continuam a existir mesmo se você deletar o container. 21 | 22 | # Volumes do tipo bind 23 | 24 | Primeiro, vamos ver como funciona da maneira antiga, que ainda é suportada, porém não é elegante. :) 25 | 26 | Essa maneira é muito utilizada quando se quer montar um diretório específico do host dentro do container. Isso é ruim quando estamos trabalhando em cluster, uma vez que teríamos que garantir esse diretório criado em todos os hosts do cluster. Não seria legal. 27 | 28 | Porém, podemos aprender como funciona e utilizar em algum momento, caso se faça necessário. Para evitar erros, primeiro crie o diretório "/volume" na sua máquina. 29 | 30 | ``` 31 | root@linuxtips:~# mkdir /volume 32 | root@linuxtips:~# docker container run -ti --mount type=bind,src=/volume,dst=/volume ubuntu 33 | root@7db02e999bf2:/# df -h 34 | 35 | Filesystem Size Used Avail Use% Mounted on 36 | none 13G 6.8G 5.3G 57% / 37 | tmpfs 999M 0 999M 0% /dev 38 | tmpfs 999M 0 999M 0% /sys/fs/cgroup 39 | /dev/mapper/ubuntu--vg-root 13G 6.8G 5.3G 57% /volume 40 | shm 64M 0 64M 0% /dev/shm 41 | 42 | root@7db02e999bf2:/# ls 43 | bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var volume 44 | ``` 45 | 46 | No exemplo anterior, conhecemos um novo parâmetro do comando "docker container run", o "--mount". 47 | 48 | O parâmetro "--mount" é o responsável por indicar o volume, que em nosso exemplo é o "/volume", e onde ele será montado no container. Perceba que, quando passamos o parâmetro "--mount type=bind,src=/volume,dst=/volume", o Docker montou esse diretório no container, porém sem nenhum conteúdo. 49 | 50 | Podemos também montar um volume no container linkando-o com um diretório do host já com algum conteúdo. Para exemplificar, vamos compartilhar o diretório "/root/primeiro_container", que utilizamos para guardar o nosso primeiro dockerfile, e montá-lo no container em um volume chamado "/volume" da seguinte forma: 51 | 52 | ``` 53 | # docker container run -ti --mount type=bind,src=/root/primeiro_container,dst=/volume ubuntu 54 | 55 | root@3d372a410ea2:/# df -h 56 | Filesystem Size Used Avail Use% Mounted on 57 | none 13G 6.8G 5.3G 57% / 58 | tmpfs 999M 0 999M 0% /dev 59 | tmpfs 999M 0 999M 0% /sys/fs/cgroup 60 | /dev/mapper/ubuntu--vg-root 13G 6.8G 5.3G 57% /volume 61 | shm 64M 0 64M 0% /dev/shm 62 | 63 | ``` 64 | 65 | Com isso, estamos montando o diretório "/root/primeiro_dockerfile" do host dentro do container com o nome de "/volume". 66 | 67 | No container: 68 | 69 | ``` 70 | root@3d372a410ea2:/# ls /volume/ 71 | Dockerfile 72 | 73 | ``` 74 | 75 | No host: 76 | 77 | ``` 78 | root@linuxtips:~# ls /root/primeiro_dockerfile/ 79 | Dockerfile 80 | 81 | root@linuxtips:~# 82 | ``` 83 | 84 | Caso eu queira deixar o volume no container apenas como read-only, é possível. Basta passar o parâmetro "ro" após o destino onde será montado o volume: 85 | 86 | ``` 87 | # docker container run -ti --mount type=bind,src=/root/primeiro_container,dst=/volume,ro ubuntu 88 | root@8d7863b1d9af:/# df -h 89 | 90 | Filesystem Size Used Avail Use% Mounted on 91 | none 13G 6.8G 5.3G 57% / 92 | tmpfs 999M 0 999M 0% /dev 93 | tmpfs 999M 0 999M 0% /sys/fs/cgroup 94 | /dev/mapper/ubuntu--vg-root 13G 6.8G 5.3G 57% /volume 95 | shm 64M 0 64M 0% /dev/shm 96 | 97 | root@8d7863b1d9af:/# cd /volume/ 98 | root@8d7863b1d9af:/volume# ls 99 | Dockerfile 100 | 101 | root@8d7863b1d9af:/volume# mkdir teste 102 | mkdir: cannot create directory 'teste': Read-only file system 103 | 104 | ``` 105 | 106 | Assim como é possível montar um diretório como volume, também é possível montar um arquivo: 107 | 108 | ``` 109 | # docker container run -ti --mount type=bind,src=/root/primeiro_container/Dockerfile,dst=/Dockerfile ubuntu 110 | 111 | root@df0e3e58280a:/# df -h 112 | 113 | Filesystem Size Used Avail Use% Mounted on 114 | none 13G 6.8G 5.3G 57% / 115 | tmpfs 999M 0 999M 0% /dev 116 | tmpfs 999M 0 999M 0% /sys/fs/cgroup 117 | /dev/mapper/ubuntu--vg-root 13G 6.8G 5.3G 57% /Dockerfile 118 | shm 64M 0 64M 0% /dev/shm 119 | 120 | root@df0e3e58280a:/# cat Dockerfile 121 | FROM debian 122 | RUN /bin/echo "HELLO DOCKER" 123 | 124 | root@df0e3e58280a:/# 125 | ``` 126 | 127 | Isso faz com que o arquivo "/root/primeiro_dockerfile/Dockerfile" seja montado em "/Dockerfile" no container. 128 | 129 | # Volumes do tipo volume 130 | 131 | Agora vamos criar os volumes da maneira mais elegante e atual. Hoje temos a possibilidade de realizar o gerenciamento de volumes de maneira muito simples e inteligente. 132 | 133 | Sempre que criamos um volume, ele cria um diretório com o mesmo nome dentro de "/var/lib/docker/volumes/". 134 | 135 | No exemplo a seguir, o volume "giropops" seria então criado em "/var/lib/docker/volumes/giropops"; com isso, todos os arquivos disponíveis nesse diretório também estariam disponíveis no local indicado no container. Vamos aos exemplos! :D 136 | 137 | É possível fazer a criação de volumes e toda a sua administração através do comando: 138 | 139 | ``` 140 | docker volume create giropops 141 | ``` 142 | 143 | É possível removê-lo através do comando: 144 | 145 | ``` 146 | docker volume rm giropops 147 | ``` 148 | 149 | Para verificar detalhes sobre esse volume: 150 | 151 | ``` 152 | docker volume inspect giropops 153 | ``` 154 | 155 | Para remover os volumes que não estão sendo utilizados (use com extrema moderação! :D): 156 | 157 | ``` 158 | docker volume prune 159 | ``` 160 | 161 | Para que você possa montar o volume criado em algum container/service, basta executar o seguinte comando: 162 | 163 | ``` 164 | docker container run -d --mount type=volume,source=giropops,destination=/var/opa nginx 165 | ``` 166 | 167 | Onde: 168 | 169 | **--mount** -- Comando utilizado para montar volumes. 170 | 171 | **type=volume** -- Indica que o tipo é "volume". Ainda existe o tipo "bind", onde, em vez de indicar um volume, você indicaria um diretório como source. 172 | 173 | **source=giropops** -- Qual o volume que pretendo montar. 174 | 175 | **destination=/var/opa** -- Onde no container montarei esse volume. 176 | 177 | ## Localizando volumes 178 | 179 | Caso você queira obter a localização do seu volume, é simples. Mas para isso você precisa conhecer o comando "docker volume inspect". 180 | 181 | Com o "docker volume inspect" você consegue obter detalhes do seu `container`, como, por exemplo, detalhes do volume. 182 | 183 | A saída do comando "docker volume inspect" retorna mais informação do que somente o `path` do diretório no `host`. Vamos usar a opção "--format" ou "-f" para filtrar a saída do "inspect". 184 | 185 | ``` 186 | docker volume inspect --format '{{ .Mountpoint }}' giropops 187 | /var/lib/docker/volumes/giropopos/_data 188 | ``` 189 | -------------------------------------------------------------------------------- /docs/docker/day-5/README.md: -------------------------------------------------------------------------------- 1 | # Descomplicando networks no Docker 2 | 3 | O Docker oferece vários tipos de drivers de rede para atender a diferentes necessidades. Aqui estão os principais: 4 | 5 | - **Bridge (Ponte)**: Este é o driver de rede padrão. Quando você cria uma rede sem especificar um driver, ela é do tipo bridge. Redes bridge são comumente usadas quando seus contêineres precisam se comunicar com outros contêineres no mesmo host. 6 | 7 | - **Host (Hospedeiro)**: Remove o isolamento de rede entre o contêiner e o host do Docker, permitindo que o contêiner use diretamente a rede do host. 8 | 9 | - **Overlay (Sobreposição)**: Redes overlay conectam vários daemons do Docker e permitem que serviços e contêineres do Swarm se comuniquem entre nós. Isso elimina a necessidade de roteamento em nível de sistema operacional1. 10 | 11 | - **IPvlan**: Redes IPvlan oferecem controle total sobre os endereços IPv4 e IPv6. O driver VLAN baseia-se nisso, fornecendo controle completo sobre a marcação de VLAN de camada 2 e até mesmo roteamento IPvlan de camada 3 para integração de rede de infraestrutura. 12 | 13 | - **Macvla**n: Redes Macvlan permitem atribuir um endereço MAC a um contêiner, fazendo com que ele pareça um dispositivo físico em sua rede. O daemon do Docker roteia o tráfego para os contêineres com base em seus endereços MAC. É útil quando você está migrando de uma configuração de máquina virtual ou quando seus contêineres precisam se parecer com hosts físicos na rede, cada um com um endereço MAC exclusivo. 14 | 15 | - **None (Nenhum)**: Isola completamente um contêiner do host e de outros contêineres. O driver none não está disponível para serviços do Swarm. 16 | 17 | - **Plugins de Rede**: Você pode instalar e usar plugins de rede de terceiros com o Docker. Esses plugins permitem integrar o Docker com pilhas de rede especializadas. 18 | 19 | Em resumo: 20 | 21 | 1. Bridge: Para contêineres que não exigem capacidades de rede especiais. 22 | 2. User-defined bridge: Para comunicação entre contêineres no mesmo host. 23 | 3. Host: Compartilha a rede do host com o contêiner. 24 | 4. Overlay: Para comunicação entre contêineres em diferentes hosts Docker. 25 | 5. Macvlan: Para migração de VMs ou quando os contêineres devem se parecer com hosts físicos. 26 | 6. IPvlan: Similar ao Macvlan, mas sem atribuição de MAC exclusivo. 27 | 28 | **Plugins de rede: Integração com pilhas de rede personalizadas**. 29 | 30 | 31 | ## Criação de rede Docker 32 | 33 | O comando `docker network create` é usado para criar uma nova rede no Docker. No exemplo fornecido, a rede é chamada de "giropops". 34 | 35 | Este comando é útil quando você precisa criar uma rede personalizada para conectar contêineres Docker. As redes Docker permitem que os contêineres se comuniquem entre si, mesmo que estejam em hosts diferentes. 36 | 37 | ``` 38 | docker network create giropops 39 | ``` 40 | 41 | ### Criando um rede overlay 42 | 43 | ``` 44 | docker network create -d overlay strigus 45 | ``` 46 | 47 | Erro de resposta do daemon: Este nó não é um gerenciador de swarm. Use "docker swarm init" ou "docker swarm join" para conectar este nó ao swarm e tente novamente. 48 | 49 | ### Criação de Rede Docker usando o driver macvlan 50 | 51 | Este comando cria uma rede Docker usando o driver macvlan. O driver macvlan permite que os contêineres Docker se conectem diretamente à rede física, obtendo um endereço IP da rede externa. 52 | 53 | 54 | **Opções:** 55 | 56 | - `docker network create`: Comando para criar uma rede Docker. 57 | 58 | - `-d macvlan`: Opção para especificar o driver macvlan. 59 | 60 | - `strigus`: Nome da rede Docker a ser criada. 61 | 62 | 63 | ``` 64 | docker network create -d macvlan strigus 65 | ``` 66 | 67 | ### Inspecionando uma rede 68 | 69 | O comando `docker network inspect` é usado para obter informações detalhadas sobre uma rede Docker específica. Ele exibe informações como o nome da rede, o ID, a data de criação, o driver de rede, as configurações de IP, entre outras informações. 70 | 71 | ``` 72 | docker network inspect 297669d965bf 73 | [ 74 | { 75 | "Name": "strigus", 76 | "Id": "297669d965bfb9a7dc0359c8bc8aeecc9420bd0d402d659e1903181aa49d31f5", 77 | "Created": "2024-04-01T13:48:59.212234154Z", 78 | "Scope": "local", 79 | "Driver": "macvlan", 80 | "EnableIPv6": false, 81 | "IPAM": { 82 | "Driver": "default", 83 | "Options": {}, 84 | "Config": [ 85 | { 86 | "Subnet": "172.20.0.0/16", 87 | "Gateway": "172.20.0.1" 88 | } 89 | ] 90 | }, 91 | "Internal": false, 92 | "Attachable": false, 93 | "Ingress": false, 94 | "ConfigFrom": { 95 | "Network": "" 96 | }, 97 | "ConfigOnly": false, 98 | "Containers": {}, 99 | "Options": {}, 100 | "Labels": {} 101 | } 102 | ] 103 | ``` 104 | 105 | 106 | ### Removendo uma rede 107 | 108 | Este comando remove uma rede Docker com o ID especificado. O parâmetro "-f" força a remoção da rede, mesmo que ela esteja sendo usada por algum container. 109 | 110 | **Parâmetros:** 111 | 112 | - network: O ID ou nome da rede Docker a ser removida. 113 | 114 | - -f: Força a remoção da rede, mesmo que ela esteja sendo usada por algum container. 115 | 116 | ``` 117 | docker network rm -f 36abd399b848 118 | ``` 119 | 120 | 121 | ### Conectando os containers em uma rede 122 | 123 | Redis 124 | ``` 125 | docker run -d --name redis --network giropops-senhas -p 6379:6379 redis 126 | ``` 127 | 128 | Aplicação 129 | 130 | ``` 131 | docker run -d --name giropops-senhas --env REDIS_HOST=172.21.0.2 -p 5000:5000 nataliagranato/linuxtips-giropops-senhas:72c0140-20240328202320 132 | ``` 133 | Mesmo depois de conectados na mesma rede, a aplicação retornava uma erro 500. Porque até aqui não informamos ao container da aplicação a rede que deve compartilhar com o redis, ambos possuem o mesmo IP. 134 | 135 | ``` 136 | ❯ docker inspect e185 | grep IPAddress 137 | "SecondaryIPAddresses": null, 138 | "IPAddress": "172.17.0.2", 139 | "IPAddress": "172.17.0.2", 140 | ❯ docker inspect 0750 | grep IPAddress 141 | "SecondaryIPAddresses": null, 142 | "IPAddress": "", 143 | "IPAddress": "172.21.0.2", 144 | ``` 145 | 146 | A aplicação funcionaria se informassemos o Gateway de rede assim: `docker run -d --name giropops-senhas --env REDIS_HOST=172.21.0.1 -p 5000:5000 nataliagranato/linuxtips-giropops-senhas:72c0140-20240328202320` 147 | 148 | 149 | Para corrigir o problema devemos iniciar a aplicação com as configurações de rede corretas: 150 | 151 | ``` 152 | docker run -d --name giropops-senhas --network giropops-senhas --env REDIS_HOST=redis -p 5000:5000 nataliagranato/linuxtips-giropops-senhas:72c0140-20240328202320 153 | ``` 154 | 155 | ### Conectando containers em uma network temporariamente 156 | 157 | O comando `docker network connect` é usado para conectar um container existente a uma rede Docker específica. Ele permite que você adicione um container a uma rede já existente, permitindo a comunicação entre os containers na mesma rede. 158 | 159 | ``` 160 | docker network connect giropops-senhas giropops-senhas 161 | ``` 162 | 163 | O comando `docker network prune` é usado para remover todas as redes Docker não utilizadas. Ele remove todas as redes que não estão sendo usadas por nenhum container em execução. 164 | 165 | ``` 166 | docker network prune 167 | ``` 168 | 169 | **Observação:** Tenha cuidado ao usar este comando, pois ele irá remover permanentemente todas as redes não utilizadas. 170 | 171 | 172 | ## Limitando a utilização de recursos dos containers 173 | 174 | Para limitar os recursos dos seus contêineres no Docker, você pode seguir as seguintes opções: 175 | 176 | **Limitando memória e CPU na linha de comando:** 177 | Para limitar a memória de um contêiner diretamente na linha de comando, use o seguinte comando: 178 | `docker run -it --memory=256M --cpus=0.5 --name meu_contêiner minha_imagem` 179 | 180 | Isso limitará o contêiner a 256 megabytes de memória e 0,5 CPUs (metade de uma CPU). 181 | 182 | **Usando o Docker Compose:** 183 | No arquivo docker-compose.yml, você pode definir limitações de recursos para seus contêineres. Por exemplo: 184 | services: 185 | ``` 186 | meu_serviço: 187 | image: minha_imagem 188 | deploy: 189 | resources: 190 | limits: 191 | cpus: "0.5" 192 | memory: 256M 193 | ``` 194 | Isso limitará o contêiner a 0,5 CPUs e 256 megabytes de memória. 195 | 196 | Lembre-se de ajustar os valores conforme suas necessidades específicas. Essas limitações ajudam a evitar que os contêineres consumam recursos excessivos e afetem o desempenho do sistema. 197 | 198 | **Valide a utilização dos recursos:** 199 | 200 | Para verificar se os recursos de CPU e memória estão limitados em um contêiner usando o comando docker container inspect, você pode seguir estas etapas: 201 | 202 | **Obtenha o ID ou nome do contêiner:** 203 | 204 | Primeiro, você precisa obter o ID ou nome do contêiner que deseja verificar. Você pode usar o comando docker ps para listar todos os contêineres em execução e encontrar o contêiner específico. 205 | 206 | Execute o comando docker container inspect: 207 | 208 | Use o seguinte comando para inspecionar o contêiner e obter informações detalhadas: 209 | `docker container inspect ` 210 | 211 | Substitua pelo nome ou ID do contêiner específico. 212 | 213 | Verifique as seções relevantes: 214 | No resultado do comando, procure pelas seções HostConfig e Config. 215 | 216 | Dentro dessas seções, você encontrará informações sobre os limites de CPU e memória definidos para o contêiner. 217 | Por exemplo, se você encontrar algo como: 218 | ``` 219 | JSON 220 | 221 | "HostConfig": { 222 | "CpuShares": 512, 223 | "Memory": 536870912 224 | }, 225 | ``` 226 | Isso significa que o contêiner está limitado a 512 unidades de CPU (CpuShares) e 512 megabytes de memória (536870912 bytes). 227 | 228 | Lembre-se de que esses valores podem variar dependendo das configurações específicas do seu contêiner. Verifique as seções relevantes no resultado do docker container inspect para obter detalhes específicos sobre os limites de recursos. 229 | 230 | Você também pode utilizar o `docker stats ` para exibir estatísticas em tempo real sobre o uso de CPU, memória, E/S e rede de um contêiner específico. -------------------------------------------------------------------------------- /docs/docker/day-6/README.md: -------------------------------------------------------------------------------- 1 | # O que é o Docker Compose? 2 | 3 | O Docker Compose é uma ferramenta exclusiva para a plataforma Docker, projetada especificamente para gerenciar containers. Ele não é compatível com outras plataformas de containers. 4 | 5 | Para ilustrar as funcionalidades do Docker Compose, vamos analisar o seguinte exemplo de um arquivo docker-compose.yml: 6 | 7 | ```yaml 8 | version: '3.9' 9 | 10 | services: 11 | giropops-senhas: 12 | build: . 13 | ports: 14 | - "5000:5000" 15 | networks: 16 | - giropops-senhas 17 | environment: 18 | - REDIS_HOST=redis 19 | volumes: 20 | - natalia:/granato 21 | deploy: 22 | replicas: 1 23 | resources: 24 | reservations: 25 | cpus: '0.25' 26 | memory: 128M 27 | limits: 28 | cpus: '0.50' 29 | memory: 256M 30 | 31 | redis: 32 | image: redis 33 | command: redis-server --appendonly yes 34 | networks: 35 | - giropops-senhas 36 | healthcheck: 37 | test: ["CMD", "curl", "-f", "http://localhost:5000"] 38 | interval: 30s 39 | timeout: 5s 40 | retries: 3 41 | start_period: 10s 42 | networks: 43 | giropops-senhas: 44 | driver: bridge 45 | 46 | volumes: 47 | natalia: 48 | ``` 49 | 50 | Neste exemplo, temos dois serviços definidos: `giropops-senhas` e `redis`. O serviço giropops-senhas é construído a partir do Dockerfile no diretório atual (indicado pelo ponto), expõe a porta 5000 e usa a rede `giropops-senhas`. Além disso, ele define uma variável de ambiente `REDIS_HOST` e utiliza um volume chamado natalia. 51 | 52 | Já o serviço redis utiliza a imagem oficial do Redis do Docker Hub, executa o servidor Redis em modo append-only e também usa a rede giropops-senhas. Além disso, ele possui um healthcheck que verifica a saúde do serviço a cada 30 segundos. 53 | 54 | A rede `giropops-senhas` é definida como uma rede do tipo bridge, e o volume natalia é criado sem qualquer configuração adicional. 55 | 56 | Este exemplo demonstra a flexibilidade e o poder do Docker Compose na definição e gerenciamento de múltiplos containers e suas interações. 57 | 58 | ## Alguns comandos para facilitar o seu dia a dia 59 | 60 | O Docker Compose é uma ferramenta que permite definir e gerenciar aplicativos multi-container. Ele utiliza um arquivo de configuração chamado docker-compose.yml para especificar os serviços, redes e volumes necessários para a execução desses contêineres. 61 | 62 | Aqui estão algumas das instruções que você mencionou e o que elas fazem: 63 | 64 | - `docker compose up -d`: Inicia os serviços definidos no arquivo docker-compose.yml em segundo plano (-d). Isso cria e inicia os contêineres conforme as configurações especificadas. 65 | - `docker compose ps`: Exibe o status dos serviços definidos no arquivo docker-compose.yml. Mostra quais contêineres estão em execução, parados ou com erro. 66 | - `docker compose down`: Encerra todos os serviços e contêineres definidos no arquivo docker-compose.yml. Isso também remove as redes e volumes associados. 67 | - `docker compose pause`: Pausa a execução dos serviços e contêineres definidos no arquivo docker-compose.yml. Isso pode ser útil para depurar ou realizar manutenção. 68 | - `docker compose unpause`: Retoma a execução dos serviços e contêineres pausados. 69 | - `docker compose logs -f`: Exibe os logs dos serviços em tempo real (-f). Isso é útil para depurar problemas ou monitorar a saída dos contêineres. 70 | 71 | ## Docker compose build, replicas e resources 72 | 73 | ### Funcionalidade `build` 74 | 75 | A funcionalidade build é utilizada no arquivo docker-compose.yml para construir a imagem de um serviço a partir de um Dockerfile localizado no diretório atual. Isso permite personalizar a imagem do serviço antes de executá-lo. 76 | 77 | Exemplo: 78 | 79 | ```yaml 80 | services: 81 | giropops-senhas: 82 | build: . 83 | ``` 84 | 85 | Neste exemplo, o serviço giropops-senhas está sendo construído a partir do Dockerfile localizado no diretório atual (.). 86 | 87 | ### Funcionalidade replicas 88 | 89 | A funcionalidade `replicas` define o número de réplicas de um serviço que serão criadas e executadas. Ela permite dimensionar horizontalmente os serviços, distribuindo a carga entre várias instâncias do mesmo serviço. 90 | 91 | Exemplo: 92 | 93 | ```yaml 94 | services: 95 | giropops-senhas: 96 | ... 97 | deploy: 98 | replicas: 3 99 | 100 | ``` 101 | 102 | Neste exemplo, o serviço `giropops-senhas` terá três réplicas em execução. 103 | 104 | ### Funcionalidade resources 105 | 106 | A funcionalidade resources permite definir limites e reservas de recursos para um serviço. Isso inclui especificações de CPU e memória para garantir que os recursos sejam alocados de forma eficiente e equitativa entre os serviços. 107 | 108 | Exemplo: 109 | 110 | ```yaml 111 | services: 112 | giropops-senhas: 113 | ... 114 | deploy: 115 | resources: 116 | reservations: 117 | cpus: '0.25' 118 | memory: 128M 119 | limits: 120 | cpus: '0.50' 121 | memory: 256M 122 | ``` 123 | 124 | Neste exemplo, o serviço `giropops-senhas` tem uma reserva de 0,25 CPUs e 128MB de memória por réplica, com um limite máximo de 0,50 CPUs e 256MB de memória por réplica. 125 | 126 | ## Comandos úteis do Docker Compose 127 | 128 | Essas funcionalidades fornecem flexibilidade e controle sobre a construção, replicação e alocação de recursos dos serviços definidos no arquivo `docker-compose.yml`. 129 | 130 | - `docker compose -f docker-compose.yml up -d`: Inicia os serviços definidos no arquivo docker-compose.yml em segundo plano (-d). Isso cria e inicia os contêineres conforme as configurações especificadas. 131 | 132 | - `docker compose -f docker-compose.yml up -d --scale redis=3`: Inicia os serviços definidos no arquivo docker-compose.yml em segundo plano (-d) e escala o serviço redis para 3 réplicas. Isso cria e inicia múltiplos contêineres do serviço redis. 133 | 134 | - `docker compose -f docker-compose.yml build`: Constrói as imagens dos serviços definidos no arquivo docker-compose.yml. Isso é útil quando você fez alterações nos Dockerfiles ou nas configurações dos serviços. 135 | 136 | Esses comandos são úteis para gerenciar e monitorar os serviços definidos no arquivo `docker-compose.yml` de forma eficiente e eficaz. 137 | 138 | # Qual é a diferença entre Docker e Docker Compose? 139 | 140 | - **Docker**: 141 | 142 | O Docker é uma plataforma de virtualização de contêineres que permite empacotar, distribuir e executar aplicativos em ambientes isolados chamados contêineres. Ele fornece uma maneira consistente de empacotar aplicativos, suas dependências e configurações em um único pacote. Cada contêiner é uma instância isolada de um aplicativo, com seu próprio sistema de arquivos, bibliotecas e recursos. O Docker usa imagens para criar contêineres. As imagens são como modelos que contêm todas as instruções para criar um contêiner. É amplamente utilizado para desenvolvimento, teste e implantação de aplicativos. 143 | 144 | - **Docker Compose**: 145 | 146 | O Docker Compose é uma ferramenta que simplifica a orquestração de vários contêineres. Ele permite definir e gerenciar aplicativos multi-container usando um arquivo de configuração chamado docker-compose.yml. No arquivo docker-compose.yml, você pode especificar serviços, redes, volumes e outras configurações necessárias para seus contêineres. Com o Docker Compose, você pode iniciar, parar, escalar e gerenciar todos os contêineres de um aplicativo com um único comando. É útil para cenários em que você precisa executar vários contêineres juntos, como aplicativos que dependem de bancos de dados, cache, servidores web, etc. 147 | 148 | Em resumo, o Docker é a base para criar e executar contêineres individuais, enquanto o Docker Compose é usado para definir e gerenciar aplicativos compostos por vários contêineres interconectados. Ambos são essenciais para o desenvolvimento e implantação eficiente de aplicativos baseados em contêineres. 🐳 149 | 150 | Espero que essas informações sejam úteis para você! Se tiver mais dúvidas ou precisar de mais informações, não hesite em perguntar. 151 | -------------------------------------------------------------------------------- /docs/docker/day-6/files/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | 3 | services: 4 | giropops-senhas: 5 | build: . 6 | ports: 7 | - "5000:5000" 8 | networks: 9 | - giropops-senhas 10 | environment: 11 | - REDIS_HOST=redis 12 | volumes: 13 | - natalia:/granato 14 | deploy: 15 | replicas: 1 16 | resources: 17 | reservations: 18 | cpus: '0.25' 19 | memory: 128M 20 | limits: 21 | cpus: '0.50' 22 | memory: 256M 23 | 24 | redis: 25 | image: redis 26 | command: redis-server --appendonly yes 27 | networks: 28 | - giropops-senhas 29 | healthcheck: 30 | test: ["CMD", "curl", "-f", "http://localhost:5000"] 31 | interval: 30s 32 | timeout: 5s 33 | retries: 3 34 | start_period: 10s 35 | networks: 36 | giropops-senhas: 37 | driver: bridge 38 | 39 | volumes: 40 | natalia: -------------------------------------------------------------------------------- /docs/k8s/day-1/README.md: -------------------------------------------------------------------------------- 1 | # Container 2 | 3 | Um container é um ambiente isolado contido em um servidor que, diferentemente das máquinas virtuais, divide um único host de controle. Ele é um ambiente isolado utilizado para empacotar aplicações, com o objetivo de segregar e facilitar a portabilidade de aplicações em diferentes ambientes. 4 | 5 | ## Container Engine 6 | 7 | Um Container Engine é uma plataforma que permite criar e executar aplicações em containers. Ele é responsável por tudo, desde a obtenção de imagens de container de um registro até a execução dos containers em seu sistema. 8 | 9 | ## Container Runtime 10 | 11 | O Container Runtime é o software responsável por executar os containers. Ele é responsável por tudo, desde a obtenção de imagens de container de um registro e gerenciamento de seu ciclo de vida até a execução dos containers em seu sistema. 12 | 13 | Existem três tipos principais de Container Runtime: 14 | 15 | - **Low-level**: Focam mais na execução de containers, configurando o namespace e cgroups para containers. 16 | - **High-level**: Focam em formatos, descompactação, gerenciamento e compartilhamento de imagens. Eles também fornecem APIs para desenvolvedores. 17 | - **Sandbox e Virtualized**: São runtimes que fornecem um ambiente isolado para executar containers. 18 | 19 | ## OCI - Open Container Initiative 20 | 21 | A Open Container Initiative (OCI) é uma estrutura de governança aberta, formada sob os auspícios da Linux Foundation, com o propósito expresso de criar padrões industriais abertos em torno de formatos de container e runtimes. Foi lançada em junho de 2015 pela Docker, CoreOS e outros líderes da indústria de containers. 22 | 23 | ## O que é o Kubernetes 24 | 25 | O Kubernetes, também conhecido como “k8s” , é uma plataforma de código aberto que automatiza os processos de implantação, gerenciamento e dimensionamento de aplicações conteinerizadas. Ele foi inicialmente desenvolvido por engenheiros do Google antes de ser disponibilizado como código aberto em 2014. 26 | 27 | ## Arquitetura do Kubernetes 28 | 29 | ![Imagem](https://miro.medium.com/v2/resize:fit:952/1*yq0bky23otUFDU1DbUftGg.png) 30 | 31 | A arquitetura do Kubernetes é composta por um conjunto de máquinas físicas ou virtuais, chamadas nós, que executam as cargas de trabalho dos aplicativos. Esses nós são gerenciados por um conjunto de componentes conhecidos como plano de controle (control plane). 32 | 33 | ### O plano de controle inclui os seguintes componentes 34 | 35 | - **API Server (kube-apiserver)** 36 | 37 | É o ponto central de coordenação de todo o sistema, expondo a API do Kubernetes via JSON sobre HTTP. Ele processa e valida solicitações REST e atualiza o estado do cluster para refletir a intenção expressa nas solicitações. 38 | 39 | - **Scheduler (kube-scheduler)** 40 | 41 | É responsável por decidir em qual nó uma carga de trabalho (por exemplo, pods) deve ser executada, com base em vários fatores, como recursos disponíveis, restrições de afinidade/anti-afinidade, etc. 42 | 43 | - **Controller Manager (kube-controller-manager)** 44 | 45 | Executa uma variedade de controladores de nível de cluster, como o controlador de replicação (que mantém o número correto de pods para cada objeto de replicação no sistema), controladores de endpoints, controladores de namespaces e outros. 46 | 47 | - **etcd** 48 | 49 | É um banco de dados distribuído e consistente que armazena a configuração do cluster e o estado atual do cluster. É o "banco de dados" para o Kubernetes. 50 | 51 | ### Cada nó do worker executa dois tipos de componentes 52 | 53 | - **Kubelet** 54 | 55 | É o agente que se comunica com o plano de controle e garante que os contêineres estejam rodando nos pods conforme o esperado. 56 | 57 | - **Kube-proxy** 58 | 59 | Mantém as regras de rede nos nós para permitir a comunicação com seus Pods a partir de dentro ou fora do cluster. 60 | 61 | - **Container Runtime** 62 | 63 | É o software responsável por executar contêineres. Pode ser Docker, containerd, CRI-O, entre outros. 64 | 65 | Além disso, os Pods são a menor unidade implantável que podem ser criados e gerenciados no Kubernetes. 66 | 67 | ### Kubernetes vs Docker 68 | 69 | Embora o Docker seja uma plataforma que permite a construção, distribuição e execução de contêineres, o Kubernetes é uma plataforma de orquestração de contêineres para plataformas como o Docker. O Kubernetes e o Docker trabalham em harmonia para criar um ecossistema completo para o desenvolvimento, implantação e gerenciamento conteinerizado. 70 | 71 | ### Como o Kubernetes surgiu? 72 | 73 | O Kubernetes surgiu como um projeto do Google no início dos anos 2000. Naquela época, o Google tinha desenvolvido um sistema de orquestração de aplicativos chamado “Borg System”. Com o surgimento dos contêineres Docker em 2013, vários membros do Projeto Borg do Google decidiram avançar com a ideia e assim surgiu o Kubernetes. 74 | 75 | # Kubernetes: Conceitos e Instalação 76 | 77 | ## Pods, ReplicaSets, Deployments e Services 78 | 79 | Os Pods são a menor unidade de um cluster Kubernetes e é onde a sua aplicação será executada. Cada Pod tem seu próprio endereço IP e compartilha um namespace PID, rede e nome de host. 80 | 81 | Um ReplicaSet é um processo que executa várias instâncias de um pod e mantém o número especificado de pods constante. Seu objetivo é manter o número especificado de instâncias de Pod em execução em um cluster a qualquer momento para evitar que os usuários percam o acesso ao aplicativo quando um Pod falhar ou estiver inacessível. 82 | 83 | Deployments são responsáveis pelo controle de versões no Kubernetes, gerando versões do ReplicaSet. 84 | 85 | Services são objetos do Kubernetes que fornecem uma abstração de nível superior para os pods e permitem que os mesmos sejam acessados por outros componentes do cluster. 86 | 87 | ## Instalando o primeiro cluster com o Kind 88 | 89 | Para instalar o Kind, é necessário ter instalados o Docker e o Go. Uma vez instalado, estamos prontos para criar nosso primeiro cluster. Criar um novo cluster é tão fácil quanto rodar o comando `kind create cluster`. 90 | 91 | ## Conhecendo o YAML e o kubectl com dry-run 92 | 93 | O comando `kubectl` com a opção `--dry-run=client -o yaml` permite testar a implantação de um arquivo YAML antes de realmente implantá-lo. Isso simula a implantação do arquivo, exibe a configuração resultante e alerta sobre quaisquer problemas que possam surgir durante a implantação real. 94 | 95 | ## Explicação das portas 96 | 97 | No Kubernetes, o **Control Plane** é composto por vários componentes que **gerenciam o estado do cluster**. As portas de comunicação permitem que os contêineres se comuniquem entre si e com o mundo externo. Aqui estão as portas usadas pelo Control Plane: 98 | 99 | - **TCP Inbound** 6443*: Kubernetes API server, usado por todos. 100 | - **TCP Inbound** 2379-2380: etcd server client API, usado pelo kube-apiserver e etcd. 101 | - **TCP Inbound** 10250: Kubelet API, usado pelo kubeadm e pelo Control Plane. 102 | - **TCP Inbound** 10259: kube-scheduler, usado pelo kubeadm. 103 | - **TCP Inbound** 10257: kube-controller-manager, usado pelo kubeadm. 104 | 105 | **Os Workers são os nós onde são processados os aplicativos**. Aqui estão as portas usadas pelos Workers: 106 | 107 | - **TCP Inbound** 10250: Kubelet API, usado pelo próprio e pelo Control Plane. 108 | - **TCP Inbound** 30000-32767: NodePort, usado por todos os Services. 109 | 110 | As portas marcadas com * são customizáveis, você precisa se certificar que a porta alterada também esteja aberta. 111 | 112 | ### Referências 113 | 114 | - [Documentação do Kubernetes - Conceitos de Containers](https://kubernetes.io/pt-br/docs/concepts/containers/) 115 | - [Wiz Academy - Runtimes de Containers](https://www.wiz.io/academy/container-runtimes) 116 | - [Open Containers Initiative](https://opencontainers.org/) 117 | - [Kubernetes - Site Oficial](https://kubernetes.io/) 118 | - [Artigo Comparativo entre Kubernetes e Docker](https://www.itprotoday.com/containers/kubernetes-vs-docker-what-s-difference) 119 | - [História do Kubernetes](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) 120 | - [An Introduction to Kubernetes (DigitalOcean)](https://www.digitalocean.com/community/tutorials/an-introduction-to-kubernetes) 121 | - [What is Kubernetes? (Red Hat)](https://www.redhat.com/en/topics/containers/what-is-kubernetes) 122 | -------------------------------------------------------------------------------- /docs/k8s/day-1/TROUBLOUSHOOTING.yml: -------------------------------------------------------------------------------- 1 | O troubleshooting, ou solução de problemas, é o processo de identificar, diagnosticar e resolver problemas em um sistema ou processo que não está funcionando conforme o esperado. No contexto de tecnologia da informação (TI), o troubleshooting é uma habilidade crucial para profissionais de suporte técnico, administradores de sistemas, engenheiros de rede e outros profissionais de TI. 2 | 3 | ### O que há de errado com o manifesto a seguir? 4 | 5 | ``` 6 | apiVersion: v1beta1 7 | kind: pods 8 | metadata: 9 | labels: 10 | run: nginx-giropops 11 | app: giropops-strigus 12 | name: nginx_giropops 13 | spec: 14 | containers: 15 | - image: nginx 16 | name: nginx_giropops 17 | ports: 18 | - containerPort: 80 19 | resources: 20 | limits: 21 | memory: 22 | cpu: "0.5" 23 | requests: 24 | memory: "4400MB" 25 | cpu: "0,3" 26 | dnsPolicy: ClusterSecond 27 | restartPolicy: Always 28 | ``` 29 | 30 | Há alguns problemas de formatação e de uso incorreto de campos no arquivo YAML fornecido, é importante se atentar a versão da `apiVersion` do Kubernetes. Aqui está uma versão corrigida: 31 | 32 | ``` 33 | apiVersion: v1 34 | kind: Pod 35 | metadata: 36 | labels: 37 | run: nginx-giropops 38 | app: giropops-strigus 39 | name: nginx-giropops 40 | spec: 41 | containers: 42 | - image: nginx 43 | name: nginx-giropops 44 | ports: 45 | - containerPort: 80 46 | resources: 47 | limits: 48 | memory: "4400Mi" 49 | cpu: "500m" 50 | requests: 51 | memory: "4400Mi" 52 | cpu: "300m" 53 | dnsPolicy: ClusterFirst 54 | restartPolicy: Always 55 | ``` 56 | 57 | Há alguns problemas de formatação e de uso incorreto de campos no arquivo YAML fornecido. Aqui está uma versão corrigida: 58 | 59 | ```yaml 60 | apiVersion: v1 61 | kind: Pod 62 | metadata: 63 | labels: 64 | run: nginx-giropops 65 | app: giropops-strigus 66 | name: nginx-giropops 67 | spec: 68 | containers: 69 | - image: nginx 70 | name: nginx-giropops 71 | ports: 72 | - containerPort: 80 73 | resources: 74 | limits: 75 | memory: "4400Mi" 76 | cpu: "500m" 77 | requests: 78 | memory: "4400Mi" 79 | cpu: "300m" 80 | dnsPolicy: ClusterFirst 81 | restartPolicy: Always 82 | ``` 83 | 84 | Aqui estão as correções realizadas: 85 | 86 | 1. `**apiVersion**`: A versão `v1beta1` foi substituída por `v1`, que é a versão atualmente suportada. 87 | 2. `**kind**`: Alterei o tipo de objeto para `Pod`, que é o correto para definir um pod. 88 | 3. `**name**`: O nome do pod agora segue a convenção camelCase, alterando `nginx_giropops` para `nginx-giropops`. 89 | 4. `**resources**`: Os campos `limits` e `requests` foram corrigidos para seguir a formatação correta. No campo `limits`, a unidade de memória foi alterada de `MB` para `Mi` e a unidade de CPU foi alterada de `0.5` para `500m` (milicores). No campo `requests`, a unidade de memória foi alterada de `MB` para `Mi` e a unidade de CPU foi alterada de `,3` para `300m`. 90 | 5. `**dnsPolicy**`: Alterei de `ClusterSecond` para `ClusterFirst`, que é o padrão e mais comum. 91 | 6. `**restartPolicy**`: Mantive como `Always`, pois é o comportamento padrão para a política de reinicialização de um pod. 92 | 93 | Essas correções devem resolver os problemas de formatação e uso incorreto de campos no arquivo YAML fornecido. 94 | -------------------------------------------------------------------------------- /docs/k8s/day-1/files/kind.yml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: worker 5 | - role: worker 6 | - role: worker 7 | - role: control-plane 8 | kubeadmConfigPatches: 9 | - | 10 | kind: InitConfiguration 11 | nodeRegistration: 12 | kubeletExtraArgs: 13 | node-labels: "ingress-ready=true" 14 | extraPortMappings: 15 | - containerPort: 80 16 | hostPort: 80 17 | protocol: TCP 18 | - containerPort: 443 19 | hostPort: 443 20 | protocol: TCP 21 | 22 | -------------------------------------------------------------------------------- /docs/k8s/day-1/files/kubernetes-ports.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Este script permite a liberação de portas necessárias para nós Kubernetes. 4 | 5 | echo "Seu nó será control-plane ou worker?" 6 | read node_type 7 | 8 | if [ "$node_type" = "control-plane" ]; then 9 | echo "Liberando portas para control-plane..." 10 | # Aqui você pode adicionar os comandos para liberar as portas necessárias. 11 | # Por exemplo, se você estiver usando o ufw (Uncomplicated Firewall) no Ubuntu, você pode fazer: 12 | sudo ufw allow 6443/tcp 13 | sudo ufw allow 2379:2380/tcp 14 | sudo ufw allow 10250/tcp 15 | sudo ufw allow 10259/tcp 16 | sudo ufw allow 10257/tcp 17 | elif [ "$node_type" = "worker" ]; then 18 | echo "Liberando portas para worker..." 19 | # Aqui você pode adicionar os comandos para liberar as portas necessárias. 20 | # Por exemplo, se você estiver usando o ufw (Uncomplicated Firewall) no Ubuntu, você pode fazer: 21 | sudo ufw allow 10250/tcp 22 | sudo ufw allow 30000:32767/tcp 23 | else 24 | echo "Tipo de nó desconhecido: $node_type" 25 | fi -------------------------------------------------------------------------------- /docs/k8s/day-1/files/tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Instalando o Docker 4 | 5 | curl https://get.docker.com | bash 6 | curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 7 | sudo chmod +x /usr/local/bin/docker-compose 8 | sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose 9 | 10 | # Instalando o Kubectl 11 | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" 12 | 13 | sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl 14 | 15 | # Instalando o Helm 16 | curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 17 | sudo chmod 700 get_helm.sh 18 | ./get_helm.sh 19 | 20 | # Instalando o Kind 21 | 22 | # For AMD64 / x86_64 23 | [ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64 24 | chmod +x ./kind 25 | sudo mv ./kind /usr/local/bin/kind 26 | -------------------------------------------------------------------------------- /docs/k8s/day-10/files/pod-monitor/nginx-pod-monitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 # versão da API 2 | kind: PodMonitor # tipo de recurso, no caso, um PodMonitor do Prometheus Operator 3 | metadata: # metadados do recurso 4 | name: nginx-podmonitor # nome do recurso 5 | labels: # labels do recurso 6 | app: nginx # label que identifica o app 7 | spec: 8 | namespaceSelector: # seletor de namespaces 9 | matchNames: # namespaces que serão monitorados 10 | - default # namespace que será monitorado 11 | selector: # seletor para identificar os pods que serão monitorados 12 | matchLabels: # labels que identificam os pods que serão monitorados 13 | app: nginx # label que identifica o app que será monitorado 14 | podMetricsEndpoints: # endpoints que serão monitorados 15 | - interval: 10s # intervalo de tempo entre as requisições 16 | path: /metrics # caminho para a requisição 17 | targetPort: 9113 # porta do target 18 | -------------------------------------------------------------------------------- /docs/k8s/day-10/files/pod-monitor/nginx-pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 # versão da API 2 | kind: Pod # tipo de recurso, no caso, um Pod 3 | metadata: # metadados do recurso 4 | name: nginx-pod # nome do recurso 5 | labels: # labels do recurso 6 | app: nginx # label que identifica o app 7 | spec: # especificações do recursos 8 | containers: # containers do template 9 | - name: nginx-container # nome do container 10 | image: nginx # imagem do container do Nginx 11 | ports: # portas do container 12 | - containerPort: 80 # porta do container 13 | name: http # nome da porta 14 | volumeMounts: # volumes que serão montados no container 15 | - name: nginx-config # nome do volume 16 | mountPath: /etc/nginx/conf.d/default.conf # caminho de montagem do volume 17 | subPath: nginx.conf # subpath do volume 18 | - name: nginx-exporter # nome do container que será o exporter 19 | image: 'nginx/nginx-prometheus-exporter:0.11.0' # imagem do container do exporter 20 | args: # argumentos do container 21 | - '-nginx.scrape-uri=http://localhost/metrics' # argumento para definir a URI de scraping 22 | resources: # recursos do container 23 | limits: # limites de recursos 24 | memory: 128Mi # limite de memória 25 | cpu: 0.3 # limite de CPU 26 | ports: # portas do container 27 | - containerPort: 9113 # porta do container que será exposta 28 | name: metrics # nome da porta 29 | volumes: # volumes do template 30 | - configMap: # configmap do volume, nós iremos criar esse volume através de um configmap 31 | defaultMode: 420 # modo padrão do volume 32 | name: nginx-config # nome do configmap 33 | name: nginx-config # nome do volume 34 | -------------------------------------------------------------------------------- /docs/k8s/day-10/files/prometheus-rules/nginx-prometheus-rule.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 # Versão da api do PrometheusRule 2 | kind: PrometheusRule # Tipo do recurso 3 | metadata: # Metadados do recurso (nome, namespace, labels) 4 | name: nginx-prometheus-rule 5 | namespace: monitoring 6 | labels: # Labels do recurso 7 | prometheus: k8s # Label que indica que o PrometheusRule será utilizado pelo Prometheus do Kubernetes 8 | role: alert-rules # Label que indica que o PrometheusRule contém regras de alerta 9 | app.kubernetes.io/name: kube-prometheus # Label que indica que o PrometheusRule faz parte do kube-prometheus 10 | app.kubernetes.io/part-of: kube-prometheus # Label que indica que o PrometheusRule faz parte do kube-prometheus 11 | spec: # Especificação do recurso 12 | groups: # Lista de grupos de regras 13 | - name: nginx-prometheus-rule # Nome do grupo de regras 14 | rules: # Lista de regras 15 | - alert: NginxDown # Nome do alerta 16 | expr: up{job="nginx"} == 0 # Expressão que será utilizada para disparar o alerta 17 | for: 1m # Tempo que a expressão deve ser verdadeira para que o alerta seja disparado 18 | labels: # Labels do alerta 19 | severity: critical # Label que indica a severidade do alerta 20 | annotations: # Anotações do alerta 21 | summary: "Nginx is down" # Título do alerta 22 | description: "Nginx is down for more than 1 minute. Pod name: {{ $labels.pod }}" # Descrição do alerta 23 | 24 | - alert: NginxHighRequestRate # Nome do alerta 25 | expr: rate(nginx_http_requests_total{job="nginx"}[5m]) > 10 # Expressão que será utilizada para disparar o alerta 26 | for: 1m # Tempo que a expressão deve ser verdadeira para que o alerta seja disparado 27 | labels: # Labels do alerta 28 | severity: warning # Label que indica a severidade do alerta 29 | annotations: # Anotações do alerta 30 | summary: "Nginx is receiving high request rate" # Título do alerta 31 | description: "Nginx is receiving high request rate for more than 1 minute. Pod name: {{ $labels.pod }}" # Descrição do alerta 32 | -------------------------------------------------------------------------------- /docs/k8s/day-10/files/service-monitor/nginx-config.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 # versão da API 2 | kind: ConfigMap # tipo de recurso, no caso, um ConfigMap 3 | metadata: # metadados do recurso 4 | name: nginx-config # nome do recurso 5 | data: # dados do recurso 6 | nginx.conf: | # inicio da definição do arquivo de configuração do Nginx 7 | server { 8 | listen 80; 9 | location / { 10 | root /usr/share/nginx/html; 11 | index index.html index.htm; 12 | } 13 | location /metrics { 14 | stub_status on; 15 | access_log off; 16 | } 17 | } -------------------------------------------------------------------------------- /docs/k8s/day-10/files/service-monitor/nginx-deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 # versão da API 2 | kind: Deployment # tipo de recurso, no caso, um Deployment 3 | metadata: # metadados do recurso 4 | name: nginx-server # nome do recurso 5 | spec: # especificação do recurso 6 | selector: # seletor para identificar os pods que serão gerenciados pelo deployment 7 | matchLabels: # labels que identificam os pods que serão gerenciados pelo deployment 8 | app: nginx # label que identifica o app que será gerenciado pelo deployment 9 | replicas: 3 # quantidade de réplicas do deployment 10 | template: # template do deployment 11 | metadata: # metadados do template 12 | labels: # labels do template 13 | app: nginx # label que identifica o app 14 | annotations: # annotations do template 15 | prometheus.io/scrape: 'true' # habilita o scraping do Prometheus 16 | prometheus.io/port: '9113' # porta do target 17 | spec: # especificação do template 18 | containers: # containers do template 19 | - name: nginx # nome do container 20 | image: nginx # imagem do container do Nginx 21 | ports: # portas do container 22 | - containerPort: 80 # porta do container 23 | name: http # nome da porta 24 | volumeMounts: # volumes que serão montados no container 25 | - name: nginx-config # nome do volume 26 | mountPath: /etc/nginx/conf.d/default.conf # caminho de montagem do volume 27 | subPath: nginx.conf # subpath do volume 28 | - name: nginx-exporter # nome do container que será o exporter 29 | image: 'nginx/nginx-prometheus-exporter:0.11.0' # imagem do container do exporter 30 | args: # argumentos do container 31 | - '-nginx.scrape-uri=http://localhost/metrics' # argumento para definir a URI de scraping 32 | resources: # recursos do container 33 | limits: # limites de recursos 34 | memory: 128Mi # limite de memória 35 | cpu: 0.3 # limite de CPU 36 | ports: # portas do container 37 | - containerPort: 9113 # porta do container que será exposta 38 | name: metrics # nome da porta 39 | volumes: # volumes do template 40 | - configMap: # configmap do volume, nós iremos criar esse volume através de um configmap 41 | defaultMode: 420 # modo padrão do volume 42 | name: nginx-config # nome do configmap 43 | name: nginx-config # nome do volume 44 | -------------------------------------------------------------------------------- /docs/k8s/day-10/files/service-monitor/nginx-pod-monitor.yml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 # versão da API 2 | kind: PodMonitor # tipo de recurso, no caso, um PodMonitor do Prometheus Operator 3 | metadata: # metadados do recurso 4 | name: nginx-podmonitor # nome do recurso 5 | labels: # labels do recurso 6 | app: nginx # label que identifica o app 7 | spec: 8 | namespaceSelector: # seletor de namespaces 9 | matchNames: # namespaces que serão monitorados 10 | - pick # namespace que será monitorado 11 | selector: # seletor para identificar os pods que serão monitorados 12 | matchLabels: # labels que identificam os pods que serão monitorados 13 | app: nginx # label que identifica o app que será monitorado 14 | podMetricsEndpoints: # endpoints que serão monitorados 15 | - interval: 10s # intervalo de tempo entre as requisições 16 | path: /metrics # caminho para a requisição 17 | targetPort: 9113 # porta do target 18 | -------------------------------------------------------------------------------- /docs/k8s/day-10/files/service-monitor/nginx-service-monitor.yml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 # versão da API 2 | kind: ServiceMonitor # tipo de recurso, no caso, um ServiceMonitor do Prometheus Operator 3 | metadata: # metadados do recurso 4 | name: nginx-servicemonitor # nome do recurso 5 | labels: # labels do recurso 6 | app: nginx # label que identifica o app 7 | spec: # especificação do recurso 8 | selector: # seletor para identificar os pods que serão monitorados 9 | matchLabels: # labels que identificam os pods que serão monitorados 10 | app: nginx # label que identifica o app que será monitorado 11 | endpoints: # endpoints que serão monitorados 12 | - interval: 10s # intervalo de tempo entre as requisições 13 | path: /metrics # caminho para a requisição 14 | targetPort: 9113 # porta do target 15 | -------------------------------------------------------------------------------- /docs/k8s/day-10/files/service-monitor/nginx-service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 # versão da API 2 | kind: Service # tipo de recurso, no caso, um Service 3 | metadata: # metadados do recurso 4 | name: nginx-svc # nome do recurso 5 | labels: # labels do recurso 6 | app: nginx # label para identificar o svc 7 | spec: # especificação do recurso 8 | ports: # definição da porta do svc 9 | - port: 9113 # porta do svc 10 | name: metrics # nome da porta 11 | selector: # seletor para identificar os pods/deployment que esse svc irá expor 12 | app: nginx # label que identifica o pod/deployment que será exposto -------------------------------------------------------------------------------- /docs/k8s/day-11/README.md: -------------------------------------------------------------------------------- 1 | # O que é o ingress no Kubernetes? 2 | 3 | O Ingress é uma API do Kubernetes que gerencia o acesso externo aos serviços em um cluster, tipicamente HTTP. O Ingress pode fornecer balanceamento de carga, SSL/TLS e hospedagem baseada em nome virtual. 4 | 5 | O Ingress é um recurso de nível de aplicativo e não é fornecido por todos os controladores de nuvem. Se o seu cluster estiver em execução em um provedor de nuvem que ofereça suporte ao LoadBalancer, o controlador de nuvem criará um serviço LoadBalancer para expor seu serviço para a Internet. 6 | 7 | ## Principais componentes do Ingress e suas funcionalidades 8 | 9 | - **Ingress Resource**: é um recurso do Kubernetes que define como o tráfego deve ser roteado para os serviços. 10 | - **Ingress Controller**: é um controlador que implementa as regras especificadas no recurso Ingress. Ele é responsável por ler as regras do recurso Ingress e configurar o balanceador de carga ou o proxy reverso de acordo com essas regras. 11 | - **Ingress Load Balancer**: é um balanceador de carga que distribui o tráfego entre os pods do serviço. Ele pode ser um balanceador de carga de camada 4 (TCP/UDP) ou de camada 7 (HTTP/HTTPS). 12 | - **Ingress Rules**: são regras que definem como o tráfego deve ser roteado para os serviços. As regras podem ser baseadas em caminhos, cabeçalhos, métodos HTTP, etc. 13 | - **Ingress Annotations**: são metadados que podem ser usados para configurar o comportamento do Ingress Controller. Eles são usados para definir configurações específicas do controlador, como redirecionamentos, regras de segurança, etc. 14 | - **Ingress TLS**: é uma configuração que permite que o tráfego seja criptografado entre o cliente e o servidor. Ele é usado para proteger os dados em trânsito e garantir a privacidade e a integridade dos dados. 15 | - **Ingress Class**: é uma configuração que permite que você defina qual controlador de Ingress deve ser usado para implementar as regras do Ingress. Isso é útil quando você tem vários controladores de Ingress em execução no cluster. 16 | - **Ingress Status**: é um status que mostra o estado atual do Ingress. Ele pode ser usado para verificar se o Ingress está funcionando corretamente e se as regras estão sendo aplicadas corretamente. 17 | - **Backend Service**: é um serviço que recebe o tráfego encaminhado pelo Ingress Controller. Ele pode ser um serviço interno ou externo, dependendo da configuração do Ingress. 18 | 19 | ## Configurando o Kind para usar o Ingress 20 | 21 | Para usar o Ingress no Kind, você precisa instalar um controlador de Ingress no cluster. Existem vários controladores de Ingress disponíveis, como o Nginx Ingress Controller, o Traefik, o HAProxy, etc. Neste exemplo, vamos usar o Nginx Ingress Controller. 22 | 23 | Quando você cria um cluster Kind, ele não tem suporte nativo para o Ingress. Para habilitar o suporte ao Ingress, você precisa especificar o controlador de Ingress que deseja usar ao criar o cluster. Você pode fazer isso passando a opção `--config` para o comando `kind create cluster` e especificando o arquivo de configuração do cluster. 24 | 25 | ```bash 26 | kind: Cluster 27 | apiVersion: kind.x-k8s.io/v1alpha4 28 | nodes: 29 | - role: control-plane 30 | kubeadmConfigPatches: 31 | - | 32 | kind: InitConfiguration 33 | nodeRegistration: 34 | kubeletExtraArgs: 35 | node-labels: "ingress-ready=true" 36 | extraPortMappings: 37 | - containerPort: 80 38 | hostPort: 80 39 | protocol: TCP 40 | - containerPort: 443 41 | ``` 42 | 43 | Obtenha o kubeconfig do cluster Kind. 44 | 45 | ```bash 46 | kind get kubeconfig --name kind > ~/.kube/kind-config-kind 47 | ``` 48 | 49 | Configure o kubeconfig para usar o cluster Kind. 50 | 51 | ```bash 52 | export KUBECONFIG=~/.kube/kind-config-kind 53 | ``` 54 | 55 | Agora faça a instalação do Nginx Ingress Controller no cluster Kind. 56 | 57 | ```bash 58 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml 59 | ``` 60 | 61 | Utilize a opção `--watch` para acompanhar a instalação do Nginx Ingress Controller. 62 | 63 | ```bash 64 | kubectl wait --namespace ingress-nginx \ 65 | --for=condition=ready pod \ 66 | --selector=app.kubernetes.io/component=controller \ 67 | --timeout=90s 68 | ``` 69 | 70 | Em um cluster gerenciado como o EKS, GKE ou AKS, o controlador de Ingress é exposto através de um Network Load Balancer. O comando para a instalação do Nginx Ingress Controller com o Helm é: 71 | 72 | ```bash 73 | helm upgrade --install ingress-nginx ingress-nginx \ 74 | --repo https://kubernetes.github.io/ingress-nginx \ 75 | --namespace ingress-nginx --create-namespace 76 | ``` 77 | 78 | Para uma listar os valores definidos no `values.yaml` do Nginx Ingress Controller, execute o comando abaixo: 79 | 80 | ```bash 81 | helm show values ingress-nginx --repo https://kubernetes.github.io/ingress-nginx 82 | ``` 83 | 84 | Se preferir instalar o Nginx Ingress Controller sem o Helm, você pode usar o comando abaixo: 85 | 86 | ```bash 87 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/cloud/deploy.yaml 88 | ``` 89 | 90 | O `kubectl` possui um plugin chamado `ingress-nginx` que pode ser usado para gerenciar o Nginx Ingress Controller. Para instalar o plugin, execute o comando abaixo: 91 | 92 | ```bash 93 | kubectl krew install ingress-nginx 94 | ``` 95 | 96 | Para verificar as suas funcionalidades utilize o comando abaixo: 97 | 98 | ```bash 99 | kubectl ingress-nginx --help 100 | ``` 101 | 102 | Entre elas estão: `logs` do ingress, `lint` para verificar possíveis problemas, `info` para ver informações do service, `conf` para inspecionar o arquivo de configuração do Nginx, etc. 103 | 104 | ## Criando nossa aplicação de exemplo 105 | 106 | Vamos criar uma aplicação de exemplo para testar o Ingress. Acessando o diretório `files` do repositório, você encontrará um arquivo chamado `app.yaml` e `redis.yaml` com a definição de um serviço e um deployment para a aplicação de exemplo e suas dependências. 107 | 108 | ```bash 109 | kubectl apply -f ./files/app/app.yaml 110 | kubectl apply -f ./files/app/redis.yaml 111 | ``` 112 | 113 | Para verificar se os recursos foram criados corretamente, execute o comando abaixo: 114 | 115 | ```bash 116 | kubectl get all 117 | ``` 118 | 119 | Agora vamos validar se a aplicação está funcionando corretamente. Para isso, vamos utilizar o comando `port-forward` do `kubectl` para encaminhar o tráfego da porta 5000 do pod para a porta 5000 do host. 120 | 121 | ```bash 122 | kubectl port-forward svc/giropops-senhas 5000:5000 123 | ``` 124 | 125 | ## Criando uma regra de Ingress 126 | 127 | Agora que a aplicação está funcionando corretamente, vamos criar uma regra de Ingress para acessar a aplicação de fora do cluster. Acesse o diretório `files` do repositório e aplique o arquivo `ingress.yaml`. 128 | 129 | ```yaml 130 | apiVersion: networking.k8s.io/v1 # apiVersion do recurso 131 | kind: Ingress # Tipo do recurso 132 | metadata: # Metadados do recurso 133 | name: giropops-senhas # Nome do recurso 134 | annotations: # Anotações do recurso onde você pode modificar o comportamento do Ingress Controller 135 | nginx.ingress.kubernetes.io/rewrite-target: / # Redireciona o tráfego para a raiz do serviço 136 | spec: # Especificação do recurso 137 | rules: # Regras do Ingress 138 | - http: # Protocolo HTTP 139 | paths: # Caminhos 140 | - path: /giropops-senhas # Caminho do serviço 141 | pathType: Prefix # Tipo do caminho 142 | backend: # Serviço de destino 143 | service: # Serviço do backend 144 | name: giropops-senhas # Nome do serviço 145 | port: # Porta do serviço 146 | number: 5000 # Número da porta 147 | ``` 148 | 149 | Após a aplicação verifique se o objeto `ingress` foi criado corretamente: 150 | 151 | ```bash 152 | kubectl get ingress 153 | ``` 154 | 155 | A saída será algo como: 156 | 157 | ```bash 158 | NAME CLASS HOSTS ADDRESS PORTS AGE 159 | giropops-senhas * localhost 80 42s 160 | ``` 161 | 162 | Para ver mais detalhes do objeto `ingress`, execute o comando abaixo: 163 | 164 | ```bash 165 | kubectl describe ingress giropops-senhas 166 | ``` 167 | 168 | A saída será algo como: 169 | 170 | ```bash 171 | Name: giropops-senhas 172 | Labels: 173 | Namespace: default 174 | Address: localhost 175 | Ingress Class: 176 | Default backend: 177 | Rules: 178 | Host Path Backends 179 | ---- ---- -------- 180 | * 181 | /giropops-senhas giropops-senhas:5000 (10.244.0.8:5000,10.244.0.9:5000) 182 | Annotations: nginx.ingress.kubernetes.io/rewrite-target: / 183 | Events: 184 | Type Reason Age From Message 185 | ---- ------ ---- ---- ------- 186 | Normal Sync 85s (x2 over 117s) nginx-ingress-controller Scheduled for sync 187 | ``` 188 | 189 | Agora você pode acessar a aplicação de fora do cluster usando o endereço `http://localhost/giropops-senhas`. Porém a aplicação está com o frontend quebrado, pois os arquivos estáticos não estão sendo servidos corretamente. Quando utilizamos a annotation `nginx.ingress.kubernetes.io/rewrite-target: /`, o Ingress Controller redireciona o tráfego para a raiz do serviço, o que faz com que os arquivos estáticos não sejam encontrados. 190 | 191 | Se removermos a annotation `nginx.ingress.kubernetes.io/rewrite-target: /`, o redirecionamento não será feito, mas ainda assim o frontend ainda estaria quebrado porque o `path` está definido como `/giropops-senhas` e o frontend espera que os arquivos estáticos sejam servidos a partir da raiz do serviço. 192 | 193 | O melhor cenário seria que o Ingress Controller servisse os arquivos estáticos a partir da raiz do serviço, mas mantendo o redirecionamento para o serviço correto. 194 | 195 | ## Corrigindo o problema dos arquivos estáticos 196 | 197 | Para corrigir isso, você precisa adicionar uma regra de Ingress para servir os arquivos estáticos. 198 | 199 | ```yaml 200 | apiVersion: networking.k8s.io/v1 201 | kind: Ingress 202 | metadata: 203 | name: giropops-senhas 204 | spec: 205 | rules: 206 | - http: 207 | paths: 208 | - path: /static 209 | pathType: Prefix 210 | backend: 211 | service: 212 | name: giropops-senhas 213 | port: 214 | number: 5000 215 | ``` 216 | 217 | ## Criando multiplos ingresses no mesmo Ingress Controller 218 | 219 | Antes de mais nada iremos criar uma outra aplicação de exemplo para testar: 220 | 221 | ```bash 222 | kubectl run nginx --image nginx --port 80 223 | ``` 224 | 225 | Vamos criar um serviço para expor a aplicação: 226 | 227 | ```bash 228 | kubectl expose po nginx 229 | ``` 230 | 231 | Agora vamos criar um ingress para a aplicação: 232 | 233 | ```yaml 234 | apiVersion: networking.k8s.io/v1 235 | kind: Ingress 236 | metadata: 237 | name: nginx 238 | annotations: 239 | nginx.ingress.kubernetes.io/rewrite-target: / 240 | spec: 241 | rules: 242 | - host: nginx.io 243 | http: 244 | paths: 245 | - path: / 246 | pathType: Prefix 247 | backend: 248 | service: 249 | name: nginx 250 | port: 251 | number: 80 252 | ``` 253 | 254 | Ele irá retornar um erro semelhante ao abaixo: 255 | 256 | ```bash 257 | Error from server (BadRequest): error when creating "ingress-4.yaml": admission webhook "validate.nginx.ingress.kubernetes.io" denied the request: host "_" and path "/" is already defined in ingress default/giropops-senhas 258 | ``` 259 | 260 | Ele bloqueou a criação porque você não pode ter duas aplicações com o mesmo host e path. Para resolver isso, você precisa definir um novo host para a aplicação. 261 | 262 | ```yaml 263 | apiVersion: networking.k8s.io/v1 264 | kind: Ingress 265 | metadata: 266 | name: giropops-senhas 267 | annotations: 268 | nginx.ingress.kubernetes.io/rewrite-target: / 269 | spec: 270 | rules: 271 | - host: senhas.io 272 | http: 273 | paths: 274 | - path: / 275 | pathType: Prefix 276 | backend: 277 | service: 278 | name: giropops-senhas 279 | port: 280 | number: 5000 281 | ``` 282 | 283 | Como estamos utilizando o Kind, você precisa adicionar o host `giropops.ngix.io` no arquivo `/etc/hosts` do seu sistema. 284 | 285 | ```bash 286 | sudo nano /etc/hosts 287 | ``` 288 | 289 | Adicione a linha abaixo no inicio do arquivo: 290 | 291 | ```bash 292 | 127.0.1.1 nginx.io 293 | ``` 294 | 295 | Faça o mesmo para a aplicação de senhas. 296 | 297 | ## Criando um cluster EKS 298 | 299 | Para criar um cluster EKS, você precisa ter o AWS CLI instalado e configurado. Você também precisa ter o eksctl instalado. Agora para criar um cluster EKS, execute o comando abaixo: 300 | 301 | ```bash 302 | eksctl create cluster --name eks-cluster --version=1.30 --region us-east-1 --nodegroup-name standard-workers --node-type t2.micro --nodes 2 --nodes-min 1 --nodes-max 3 --managed 303 | ``` 304 | 305 | ## Entendendo os Contexts para gerenciar vários clusters 306 | 307 | O `kubectl` suporta múltiplos clusters e contextos. Você pode usar o comando `kubectl config get-contexts` para listar todos os contextos disponíveis. Para verificar o contexto vigente use: 308 | 309 | ```bash 310 | kubectl config current-context 311 | ``` 312 | 313 | Para usar um contexto diferente você pode usar o comando `kubectl config use-context`: 314 | 315 | ```bash 316 | kubectl config use-context 317 | ``` 318 | -------------------------------------------------------------------------------- /docs/k8s/day-11/files/app/app.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: giropops-senhas 6 | name: giropops-senhas 7 | spec: 8 | replicas: 2 9 | selector: 10 | matchLabels: 11 | app: giropops-senhas 12 | template: 13 | metadata: 14 | labels: 15 | app: giropops-senhas 16 | spec: 17 | containers: 18 | - image: linuxtips/giropops-senhas:1.0 19 | name: giropops-senhas 20 | env: 21 | - name: REDIS_HOST 22 | value: redis-service 23 | ports: 24 | - containerPort: 5000 25 | imagePullPolicy: Always 26 | 27 | --- 28 | apiVersion: v1 29 | kind: Service 30 | metadata: 31 | name: giropops-senhas 32 | labels: 33 | app: giropops-senhas 34 | spec: 35 | selector: 36 | app: giropops-senhas 37 | ports: 38 | - protocol: TCP 39 | port: 5000 40 | targetPort: 5000 41 | name: tcp-app 42 | type: ClusterIP # Esse serviço será acessível somente dentro do cluster kubernetes 43 | -------------------------------------------------------------------------------- /docs/k8s/day-11/files/app/redis.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: redis 6 | name: redis-deployment 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: redis 12 | template: 13 | metadata: 14 | labels: 15 | app: redis 16 | spec: 17 | containers: 18 | - image: redis 19 | name: redis 20 | ports: 21 | - containerPort: 6379 22 | resources: 23 | limits: 24 | memory: "256Mi" 25 | cpu: "500m" 26 | requests: 27 | memory: "128Mi" 28 | cpu: "250m" 29 | 30 | --- 31 | apiVersion: v1 32 | kind: Service 33 | metadata: 34 | name: redis-service 35 | spec: 36 | selector: 37 | app: redis 38 | ports: 39 | - protocol: TCP 40 | port: 6379 41 | targetPort: 6379 42 | type: ClusterIP # Esse serviço será acessível somente dentro do cluster kubernetes 43 | -------------------------------------------------------------------------------- /docs/k8s/day-11/files/ingress-1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: giropops-senhas 5 | annotations: 6 | nginx.ingress.kubernetes.io/rewrite-target: / 7 | spec: 8 | rules: 9 | - http: 10 | paths: 11 | - path: /giropops-senhas 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: giropops-senhas 16 | port: 17 | number: 5000 18 | -------------------------------------------------------------------------------- /docs/k8s/day-11/files/ingress-2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: giropops-senhas 5 | spec: 6 | rules: 7 | - http: 8 | paths: 9 | - path: /static 10 | pathType: Prefix 11 | backend: 12 | service: 13 | name: giropops-senhas 14 | port: 15 | number: 5000 16 | -------------------------------------------------------------------------------- /docs/k8s/day-11/files/ingress-3.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: giropops-senhas 5 | annotations: 6 | nginx.ingress.kubernetes.io/rewrite-target: / 7 | spec: 8 | rules: 9 | - http: 10 | paths: 11 | - path: / 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: giropops-senhas 16 | port: 17 | number: 5000 18 | -------------------------------------------------------------------------------- /docs/k8s/day-11/files/ingress-4.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: nginx 5 | annotations: 6 | nginx.ingress.kubernetes.io/rewrite-target: / 7 | spec: 8 | rules: 9 | - http: 10 | paths: 11 | - path: / 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: nginx 16 | port: 17 | number: 80 18 | -------------------------------------------------------------------------------- /docs/k8s/day-11/files/ingress-5.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: nginx 5 | annotations: 6 | nginx.ingress.kubernetes.io/rewrite-target: / 7 | spec: 8 | rules: 9 | - host: nginx.io 10 | http: 11 | paths: 12 | - path: / 13 | pathType: Prefix 14 | backend: 15 | service: 16 | name: nginx 17 | port: 18 | number: 80 19 | -------------------------------------------------------------------------------- /docs/k8s/day-11/files/ingress-6.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: giropops-senhas 5 | annotations: 6 | nginx.ingress.kubernetes.io/rewrite-target: / 7 | spec: 8 | rules: 9 | - host: senhas.io 10 | http: 11 | paths: 12 | - path: / 13 | pathType: Prefix 14 | backend: 15 | service: 16 | name: giropops-senhas 17 | port: 18 | number: 5000 19 | -------------------------------------------------------------------------------- /docs/k8s/day-11/files/kind/kind-config.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: control-plane 5 | kubeadmConfigPatches: 6 | - | 7 | kind: InitConfiguration 8 | nodeRegistration: 9 | kubeletExtraArgs: 10 | node-labels: "ingress-ready=true" 11 | extraPortMappings: 12 | - containerPort: 80 13 | hostPort: 80 14 | protocol: TCP 15 | - containerPort: 443 16 | -------------------------------------------------------------------------------- /docs/k8s/day-2/README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes e Pods 2 | 3 | ## O que é um Pod no Kubernetes? 4 | 5 | Um Pod é a menor e mais simples unidade no modelo de objeto do Kubernetes. Um Pod representa um processo único em um cluster e pode conter um ou mais contêineres. Os contêineres dentro de um Pod compartilham o mesmo contexto de rede e podem se comunicar entre si usando `localhost`. 6 | 7 | ## Comandos Básicos do kubectl 8 | 9 | ### kubectl get pods 10 | 11 | Este comando lista todos os Pods que estão atualmente em execução no cluster ou no namespace especificado. 12 | 13 | Exemplo de uso: 14 | 15 | ```bash 16 | kubectl get pods 17 | ``` 18 | 19 | ### kubectl describe pod 20 | 21 | Este comando mostra detalhes sobre um Pod específico. 22 | 23 | Exemplo de uso: 24 | 25 | ```bash 26 | kubectl describe pods 27 | ``` 28 | 29 | ### Utilizando kubectl attach e kubectl exec 30 | 31 | **kubectl attach** 32 | Este comando permite que você execute um comando específico dentro de um contêiner em um Pod. 33 | 34 | Exemplo de uso: 35 | 36 | ```bash 37 | kubectl exec -- 38 | ``` 39 | 40 | **kubectl exec** 41 | Este comando permite que você execute um comando específico dentro de um contêiner em um Pod. 42 | 43 | Exemplo de uso: 44 | 45 | ```bash 46 | kubectl exec -- 47 | ``` 48 | 49 | ## Criando um Pod com Multi-contêineres 50 | 51 | Aqui está um exemplo de um manifesto para criar um Pod com vários contêineres: 52 | 53 | ```yaml 54 | apiVersion: v1 55 | kind: Pod 56 | metadata: 57 | name: meu-pod-multicontainer 58 | spec: 59 | containers: 60 | - name: nginx-container 61 | image: nginx 62 | - name: busybox-container 63 | image: busybox 64 | command: ['sh', '-c', 'echo Hello, world!'] 65 | ``` 66 | 67 | Para criar o Pod, salve o manifesto acima em um arquivo chamado meu-pod.yaml e execute o seguinte comando: 68 | 69 | ``` 70 | kubectl apply -f meu-pod.yaml 71 | ``` 72 | 73 | ## Limitando Recursos de CPU e memória de um Pod 74 | 75 | Aqui está um exemplo de um manifesto para criar um Pod com limites de recursos de CPU e memória: 76 | 77 | ```yaml 78 | apiVersion: v1 79 | kind: Pod 80 | metadata: 81 | name: meu-pod-multicontainer 82 | spec: 83 | containers: 84 | - name: nginx-container 85 | image: nginx 86 | resources: 87 | requests: 88 | memory: "64Mi" 89 | cpu: "250m" 90 | limits: 91 | memory: "128Mi" 92 | cpu: "500m" 93 | - name: busybox-container 94 | image: busybox 95 | command: ['sh', '-c', 'echo Hello, world! && sleep infinity'] 96 | 97 | ``` 98 | 99 | # Requests e Limits no Kubernetes 100 | 101 | `Requests` e `limits` são conceitos fundamentais no Kubernetes que ajudam a gerenciar o uso de recursos em um cluster. 102 | 103 | ## Requests 104 | 105 | `Requests` são o que o contêiner está garantido para ter como recurso. Quando um contêiner é criado, o Kubernetes reserva a quantidade de recurso especificada na solicitação para o contêiner. Isso é usado pelo agendador do Kubernetes para decidir em qual nó colocar o Pod. Se um nó não tem recursos suficientes disponíveis para atender à solicitação do Pod, o Pod não será agendado para aquele nó. 106 | 107 | ## Limits 108 | 109 | `Limits`, por outro lado, são a quantidade máxima de recurso que um contêiner pode usar. Se um contêiner excede o limite de um recurso, ele pode ser encerrado ou ter sua CPU limitada, dependendo do recurso e das configurações do cluster. 110 | 111 | A importância de definir `requests` e `limits` adequados é dupla: 112 | 113 | 1. **Eficiência de recursos**: Ao definir `requests` e `limits`, você pode garantir que seus Pods estão usando os recursos de maneira eficiente, sem consumir mais do que o necessário. 114 | 115 | 2. **Isolamento de recursos**: `requests` e `limits` também ajudam a evitar que um Pod monopolize todos os recursos em um nó, o que pode afetar outros Pods no mesmo nó. 116 | 117 | Portanto, é uma boa prática definir `requests` e `limits` para seus contêineres para garantir o uso eficiente dos recursos e a coexistência harmoniosa de múltiplos Pods em um único nó. 118 | -------------------------------------------------------------------------------- /docs/k8s/day-2/files/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: giropops-deployment 5 | labels: 6 | run: giropops 7 | spec: 8 | replicas: 3 9 | strategy: 10 | type: RollingUpdate 11 | rollingUpdate: 12 | maxUnavailable: 1 13 | maxSurge: 1 14 | selector: 15 | matchLabels: 16 | run: giropops 17 | template: 18 | metadata: 19 | labels: 20 | run: giropops 21 | spec: 22 | containers: 23 | - name: giropops 24 | image: nginx 25 | ports: 26 | - containerPort: 80 27 | resources: 28 | limits: 29 | memory: "128Mi" 30 | cpu: "0.5" 31 | requests: 32 | memory: "64Mi" 33 | cpu: "0.3" 34 | volumeMounts: 35 | - mountPath: /usr/share/nginx/html 36 | name: data 37 | - name: strigus 38 | image: alpine 39 | args: 40 | - sleep 41 | - "1800" 42 | volumeMounts: 43 | - mountPath: /alpine/data 44 | name: data 45 | volumes: 46 | - name: data 47 | emptyDir: {} 48 | -------------------------------------------------------------------------------- /docs/k8s/day-2/files/meu-pod-multicontainer.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: meu-pod-multicontainer 5 | spec: 6 | containers: 7 | - name: nginx-container 8 | image: nginx 9 | - name: busybox-container 10 | image: busybox 11 | command: ['sh', '-c', 'echo Hello, world! && sleep infinity'] 12 | -------------------------------------------------------------------------------- /docs/k8s/day-2/files/multicontainer-limitado.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: meu-pod-multicontainer 5 | spec: 6 | containers: 7 | - name: nginx-container 8 | image: nginx 9 | resources: 10 | requests: 11 | memory: "64Mi" 12 | cpu: "250m" 13 | limits: 14 | memory: "128Mi" 15 | cpu: "500m" 16 | - name: busybox-container 17 | image: busybox 18 | command: ['sh', '-c', 'echo Hello, world! && sleep infinity'] 19 | -------------------------------------------------------------------------------- /docs/k8s/day-3/README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Deployments 2 | 3 | ## O que é um Deployment? 4 | 5 | Um Deployment no Kubernetes é um objeto que pode declarar, atualizar e dimensionar aplicativos. Ele usa um Pod Template, que contém especificações para os Pods. O estado desejado é descrito no Deployment e o Controlador de Deployment muda o estado atual para o estado desejado em um ritmo controlado. 6 | 7 | ## Criando um Deployment 8 | 9 | Você pode criar um Deployment através de um manifesto. Aqui está um exemplo de um manifesto de Deployment: 10 | 11 | ```yaml 12 | apiVersion: apps/v1 13 | kind: Deployment 14 | metadata: 15 | name: nginx-deployment 16 | spec: 17 | selector: 18 | matchLabels: 19 | app: nginx 20 | replicas: 3 21 | template: 22 | metadata: 23 | labels: 24 | app: nginx 25 | spec: 26 | containers: 27 | - name: nginx 28 | image: nginx:1.26-bookworm 29 | ports: 30 | - containerPort: 80 31 | ``` 32 | 33 | Para criar o Deployment, você pode salvar o manifesto acima em um arquivo chamado nginx-deployment.yaml e executar o seguinte comando: 34 | 35 | ```bash 36 | kubectl apply -f nginx-deployment.yaml 37 | ``` 38 | 39 | ### Vendo os detalhes de um Deployment 40 | 41 | Você pode ver os detalhes de um Deployment usando o comando `kubectl describe`: 42 | 43 | ```bash 44 | kubectl describe deployment nginx-deployment 45 | ``` 46 | 47 | ### Atualizando um Deployment 48 | 49 | Você pode atualizar um Deployment alterando o manifesto e reaplicando-o com kubectl apply, ou pode usar o comando kubectl set image: 50 | 51 | ```bash 52 | kubectl set image deployment/nginx-deployment nginx=nginx:1.26 53 | ``` 54 | 55 | Você também pode editar o Deployment diretamente: 56 | 57 | ```bash 58 | kubectl edit deployment nginx-deployment 59 | ``` 60 | 61 | E utilizar o comando `kubectl apply` para aplicar alterações. 62 | 63 | ```bash 64 | kubectl apply -f nginx-deployment.yaml 65 | ``` 66 | 67 | ### Estratégias de atualização de um Deployment 68 | 69 | Existem duas estratégias de atualização para um Deployment: Recreate e Rolling Update. Por padrão, o Rolling Update é usado. 70 | 71 | - **Recreate**: Todos os Pods existentes são mortos antes que os novos sejam criados. Aqui está um exemplo: 72 | 73 | ```yaml 74 | apiVersion: apps/v1 75 | kind: Deployment 76 | metadata: 77 | name: nginx-deployment 78 | spec: 79 | strategy: 80 | type: Recreate 81 | selector: 82 | matchLabels: 83 | app: nginx 84 | replicas: 3 85 | template: 86 | metadata: 87 | labels: 88 | app: nginx 89 | spec: 90 | containers: 91 | - name: nginx 92 | image: nginx:1.26 93 | ports: 94 | - containerPort: 80 95 | ``` 96 | 97 | - **Rolling Update (padrão)**: O Deployment atualiza os Pods em um ritmo controlado, matando e recriando os Pods um de cada vez. Aqui está um exemplo: 98 | 99 | ```yaml 100 | apiVersion: apps/v1 101 | kind: Deployment 102 | metadata: 103 | name: nginx-deployment 104 | spec: 105 | strategy: 106 | type: RollingUpdate 107 | selector: 108 | matchLabels: 109 | app: nginx 110 | replicas: 3 111 | template: 112 | metadata: 113 | labels: 114 | app: nginx 115 | spec: 116 | containers: 117 | - name: nginx 118 | image: nginx:1.26 119 | ports: 120 | - containerPort: 80 121 | ``` 122 | 123 | ### Fazendo um Rollback de um Deployment 124 | 125 | Você pode fazer rollback para uma revisão anterior de um Deployment usando o comando `kubectl rollout undo`: 126 | 127 | ```bash 128 | kubectl rollout undo deployment/nginx-deployment 129 | ``` 130 | 131 | ### Pausando e Resumindo um Deployment 132 | 133 | Você pode pausar um Deployment para evitar que ele faça alterações nos Pods. Para pausar um Deployment, use o comando `kubectl rollout pause`: 134 | 135 | ```bash 136 | kubectl rollout pause deployment/nginx-deployment 137 | ``` 138 | 139 | O comando `kubectl rollout` permite que você gerencie a implantação gradual de atualizações para seus Deployments. Você pode pausar, retomar e verificar o status de um rollout, além de fazer rollback para uma revisão anterior. 140 | 141 | ### Escalando um Deployment 142 | 143 | Você pode escalar um Deployment alterando o número de réplicas no manifesto e reaplicando-o com kubectl apply, ou usando o comando kubectl scale: 144 | 145 | ```bash 146 | kubectl scale deployment nginx-deployment --replicas=5 147 | ``` 148 | 149 | ### Verificando o ReplicaSet que o Deployment está gerenciando 150 | 151 | Você pode verificar o ReplicaSet que um Deployment está gerenciando usando o comando `kubectl get`. Aqui está um exemplo: 152 | 153 | ```bash 154 | kubectl get rs -l app=nginx 155 | ``` 156 | 157 | Este comando lista todos os ReplicaSets que têm a label `app=nginx`, que é a label usada no Deployment do exemplo anterior. 158 | 159 | ### Excluindo um Deployment 160 | 161 | Você pode excluir um Deployment usando o comando kubectl delete: 162 | 163 | ```bash 164 | kubectl delete deployment nginx-deployment 165 | ``` 166 | -------------------------------------------------------------------------------- /docs/k8s/day-3/files/deploy-recreate.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment 5 | spec: 6 | strategy: 7 | type: Recreate 8 | selector: 9 | matchLabels: 10 | app: nginx 11 | replicas: 3 12 | template: 13 | metadata: 14 | labels: 15 | app: nginx 16 | spec: 17 | containers: 18 | - name: nginx 19 | image: nginx:1.26 20 | ports: 21 | - containerPort: 80 22 | -------------------------------------------------------------------------------- /docs/k8s/day-3/files/deploy-update.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment 5 | spec: 6 | strategy: 7 | type: RollingUpdate 8 | selector: 9 | matchLabels: 10 | app: nginx 11 | replicas: 3 12 | template: 13 | metadata: 14 | labels: 15 | app: nginx 16 | spec: 17 | containers: 18 | - name: nginx 19 | image: nginx:1.26 20 | ports: 21 | - containerPort: 80 22 | -------------------------------------------------------------------------------- /docs/k8s/day-3/files/deploy.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: nginx 9 | replicas: 3 10 | template: 11 | metadata: 12 | labels: 13 | app: nginx 14 | spec: 15 | containers: 16 | - name: nginx 17 | image: nginx:1.26-bookworm 18 | ports: 19 | - containerPort: 80 20 | -------------------------------------------------------------------------------- /docs/k8s/day-4/README.md: -------------------------------------------------------------------------------- 1 | ## O que é um ReplicaSet? 2 | 3 | Um ReplicaSet é um objeto do Kubernetes que garante que um número especificado de réplicas de um pod esteja em execução a qualquer momento. Ele é frequentemente usado para garantir a disponibilidade e a redundância dos pods. 4 | 5 | ## O Deployment e o ReplicaSet 6 | 7 | Um Deployment é um objeto do Kubernetes que fornece atualizações declarativas para Pods e ReplicaSets. Você descreve o estado desejado em um objeto Deployment e o controlador de Deployment muda o estado atual para o estado desejado em um ritmo controlado para o usuário. 8 | 9 | ## O que é um DaemonSet? 10 | 11 | Um DaemonSet garante que todos (ou alguns) os nós executem uma cópia de um Pod. À medida que os nós são adicionados ao cluster, os Pods são adicionados a eles. À medida que os nós são removidos do cluster, esses Pods são coletados como lixo. 12 | 13 | ## Criando um DaemonSet 14 | 15 | Para criar um DaemonSet, você precisa definir um arquivo YAML com as especificações do DaemonSet e usar o comando `kubectl apply -f your-daemonset.yaml` para criar o DaemonSet. Um exemplo: 16 | 17 | ```yaml 18 | apiVersion: apps/v1 19 | kind: DaemonSet 20 | metadata: 21 | name: nginx-daemonset 22 | labels: 23 | app: nginx 24 | spec: 25 | selector: 26 | matchLabels: 27 | name: nginx 28 | template: 29 | metadata: 30 | labels: 31 | name: nginx 32 | spec: 33 | containers: 34 | - name: nginx 35 | image: nginx:26 36 | ports: 37 | - containerPort: 80 38 | ``` 39 | 40 | O exemplo acima cria um DaemonSet chamado `nginx-daemonset` que garante que todos os nós do cluster tenham um pod chamado `nginx` em execução. 41 | 42 | ## O que são as probes no Kubernetes? 43 | 44 | As probes são mecanismos usados pelo Kubernetes para determinar quando reiniciar um contêiner. Kubernetes usa três tipos de probes: Readiness, Liveness e Startup. 45 | 46 | ## Exemplos de probes no Kubernetes 47 | 48 | As probes no Kubernetes são usadas para verificar o estado de um Pod e são divididas em três tipos: Liveness, Readiness e Startup. 49 | 50 | - **Liveness Probe**: Esta sonda é usada para saber quando reiniciar um contêiner. Se a liveness probe falhar, o Kubernetes irá matar o contêiner e o contêiner será recriado. 51 | 52 | - **Readiness Probe**: Esta sonda é usada para decidir quando o contêiner está pronto para aceitar tráfego. Se a readiness probe falhar, o Kubernetes irá parar de enviar tráfego para o Pod até que a sonda tenha sucesso. 53 | 54 | - **Startup Probe**: Esta sonda é usada para saber quando um contêiner começou com sucesso. Ela é usada para evitar que um contêiner seja morto pelo Kubernetes antes que esteja pronto para servir o tráfego. 55 | 56 | As probes podem ser configuradas de três maneiras: 57 | 58 | - **httpGet**: Faz uma solicitação HTTP para o contêiner. 59 | 60 | - **tcpSocket**: Faz uma solicitação TCP para o contêiner. 61 | 62 | - **exec**: Executa um comando no contêiner. 63 | 64 | Aqui estão alguns exemplos de como você pode definir probes em seu arquivo de configuração do Kubernetes: 65 | 66 | ```yaml 67 | livenessProbe: 68 | httpGet: 69 | path: /health 70 | port: 8080 71 | initialDelaySeconds: 15 72 | periodSeconds: 20 73 | 74 | readinessProbe: 75 | exec: 76 | command: 77 | - cat 78 | - /app/is_ready 79 | initialDelaySeconds: 5 80 | periodSeconds: 5 81 | 82 | startupProbe: 83 | httpGet: 84 | path: /health 85 | port: 8080 86 | failureThreshold: 30 87 | periodSeconds: 10 88 | ``` 89 | -------------------------------------------------------------------------------- /docs/k8s/day-4/files/daemonset.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: nginx-daemonset 5 | labels: 6 | app: nginx 7 | spec: 8 | selector: 9 | matchLabels: 10 | name: nginx 11 | template: 12 | metadata: 13 | labels: 14 | name: nginx 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx:1.26.0 19 | ports: 20 | - containerPort: 80 21 | -------------------------------------------------------------------------------- /docs/k8s/day-4/files/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: nginx-deployment 6 | name: nginx-deployment 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: nginx-deployment 12 | strategy: {} 13 | template: 14 | metadata: 15 | labels: 16 | app: nginx-deployment 17 | spec: 18 | containers: 19 | - image: nginx 20 | name: nginx 21 | resources: 22 | limits: 23 | cpu: "0.5" 24 | memory: 256Mi 25 | requests: 26 | cpu: "0.25" 27 | memory: 128Mi 28 | -------------------------------------------------------------------------------- /docs/k8s/day-4/files/nginx-liveness.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: nginx-deployment 6 | name: nginx-deployment 7 | spec: 8 | replicas: 3 9 | selector: 10 | matchLabels: 11 | app: nginx-deployment 12 | strategy: {} 13 | template: 14 | metadata: 15 | labels: 16 | app: nginx-deployment 17 | spec: 18 | containers: 19 | - image: nginx:1.19.2 20 | name: nginx 21 | resources: 22 | limits: 23 | cpu: "0.5" 24 | memory: 256Mi 25 | requests: 26 | cpu: "0.25" 27 | memory: 128Mi 28 | livenessProbe: # Aqui vamos definir a sonda de verificação de saúde. 29 | tcpSocket: # Vamos utilizar o protocolo TCP para a verificação. 30 | port: 80 # Vamos verificar a porta 80. 31 | initialDelaySeconds: 10 # Vamos esperar 10 segundos antes de executar a primeira verificação. 32 | periodSeconds: 10 # Vamos executar a verificação a cada 10 segundos. 33 | timeoutSeconds: 5 # Vamos esperar 5 segundos antes de considerar a verificação como falha. 34 | failureThreshold: 3 # Vamos considerar a sonda como falha após 3 tentativas. 35 | -------------------------------------------------------------------------------- /docs/k8s/day-4/files/nginx-readiness.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: nginx-deployment 6 | name: nginx-deployment 7 | spec: 8 | replicas: 3 9 | selector: 10 | matchLabels: 11 | app: nginx-deployment 12 | strategy: {} 13 | template: 14 | metadata: 15 | labels: 16 | app: nginx-deployment 17 | spec: 18 | containers: 19 | - image: nginx:1.19.2 20 | name: nginx 21 | resources: 22 | limits: 23 | cpu: "0.5" 24 | memory: 256Mi 25 | requests: 26 | cpu: "0.25" 27 | memory: 128Mi 28 | readinessProbe: # Aqui vamos definir a sonda de verificação de prontidão. 29 | httpGet: # Vamos utilizar o protocolo HTTP para a verificação. 30 | path: / # Vamos verificar a raiz do servidor. 31 | port: 80 # Vamos verificar a porta 80. 32 | initialDelaySeconds: 10 # Vamos esperar 10 segundos antes de executar a primeira verificação. 33 | periodSeconds: 10 # Vamos executar a verificação a cada 10 segundos. 34 | timeoutSeconds: 5 # Vamos esperar 5 segundos antes de considerar a verificação como falha. 35 | successThreshold: 2 # O número de vezes que a probe precisa ser bem-sucedida para considerar que o container está pronto. 36 | failureThreshold: 3 # Vamos considerar a sonda como falha após 3 tentativas. 37 | -------------------------------------------------------------------------------- /docs/k8s/day-4/files/nginx-startup.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: nginx-deployment 6 | name: nginx-deployment 7 | spec: 8 | replicas: 3 9 | selector: 10 | matchLabels: 11 | app: nginx-deployment 12 | strategy: {} 13 | template: 14 | metadata: 15 | labels: 16 | app: nginx-deployment 17 | spec: 18 | containers: 19 | - image: nginx:1.19.2 20 | name: nginx 21 | resources: 22 | limits: 23 | cpu: "0.5" 24 | memory: 256Mi 25 | requests: 26 | cpu: "0.25" 27 | memory: 128Mi 28 | startupProbe: # Aqui vamos definir a sonda de verificação de inicialização. 29 | httpGet: # Vamos utilizar o protocolo HTTP para a verificação. 30 | path: / # Vamos verificar a raiz do servidor. 31 | port: 80 # Vamos verificar a porta 80. 32 | initialDelaySeconds: 10 # Vamos esperar 10 segundos antes de executar a primeira verificação. 33 | periodSeconds: 10 # Vamos executar a verificação a cada 10 segundos. 34 | timeoutSeconds: 5 # Vamos esperar 5 segundos antes de considerar a verificação como falha. 35 | successThreshold: 2 # O número de vezes que a probe precisa ser bem-sucedida para considerar que o container está pronto. 36 | failureThreshold: 3 # Vamos considerar a sonda como falha após 3 tentativas. 37 | -------------------------------------------------------------------------------- /docs/k8s/day-4/files/replicaset.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: ReplicaSet 3 | metadata: 4 | labels: 5 | app: nginx-app 6 | name: nginx-replicaset 7 | spec: 8 | replicas: 3 9 | selector: 10 | matchLabels: 11 | app: nginx-app 12 | template: 13 | metadata: 14 | labels: 15 | app: nginx-app 16 | spec: 17 | containers: 18 | - image: nginx:1.19.2 19 | name: nginx 20 | resources: 21 | limits: 22 | cpu: "0.5" 23 | memory: 256Mi 24 | requests: 25 | cpu: "0.25" 26 | memory: 128Mi 27 | -------------------------------------------------------------------------------- /docs/k8s/day-5/EXTRAS.MD: -------------------------------------------------------------------------------- 1 | # Comandos extras para a administração de um cluster Kubernetes 2 | 3 | Os comandos abaixo são úteis para a administração de um cluster Kubernetes. 4 | 5 | ```bash 6 | 7 | # Listar os nodes do cluster 8 | kubectl get nodes -o wide 9 | 10 | # Listar os pods de do namespace kube-system 11 | kubectl get pods -n kube-system 12 | 13 | # Listar os pods de do namespace kube-system ordenados pelo nome do node 14 | kubectl get pods -n kube-system -o wide 15 | 16 | # Listar os pods de do namespace kube-system ordenados pela data de criação 17 | kubectl get pods -n kube-system -o wide --sort-by=.spec.nodeName 18 | 19 | # Listar os pods de do namespace kube-system ordenados pela data de criação e filtrando apenas os pods em execução 20 | kubectl get pods -n kube-system -o wide --sort-by=.metadata.creationTimestamp -A --field-selector=status.phase=Running 21 | 22 | # Listar os pods de do namespace kube-system ordenados pela data de criação e filtrando apenas os pods em execução do kube-proxy 23 | kubectl get pods -n kube-system -o wide --sort-by=.metadata.creationTimestamp -A --field-selector=status.phase=Running | grep -i kube-proxy 24 | 25 | # Listar os pods de do namespace kube-system ordenados pela data de criação e filtrando apenas os pods em execução do coredns 26 | kubectl get pods -n kube-system -o wide --sort-by=.metadata.creationTimestamp -A --field-selector=status.phase=Running | grep -i coredns 27 | 28 | # Listar os pods de do namespace kube-system ordenados pela data de criação e filtrando apenas os pods em execução do kube-scheduler 29 | kubectl get pods -n kube-system -o wide --sort-by=.metadata.creationTimestamp -A --field-selector=status.phase=Running | grep -i kube-scheduler 30 | 31 | # Listar os pods de do namespace kube-system ordenados pela data de criação e filtrando apenas os pods em execução do kube-controller-manager 32 | kubectl get pods -n kube-system -o wide --sort-by=.metadata.creationTimestamp -A --field-selector=status.phase=Running | grep -i kube-controller-manager 33 | 34 | # Listar os pods de do namespace kube-system ordenados pela data de criação e filtrando apenas os pods em execução do etcd 35 | kubectl get pods -n kube-system -o wide --sort-by=.metadata.creationTimestamp -A --field-selector=status.phase=Running | grep -i etcd 36 | 37 | # Listar os pods de do namespace kube-system ordenados pela data de criação e filtrando apenas os pods em execução do kube-apiserver 38 | kubectl get pods -n kube-system -o wide --sort-by=.metadata.creationTimestamp -A --field-selector=status.phase=Running | grep -i kube-apiserver 39 | ``` 40 | 41 | Por default o nó control-plane não executa pods de aplicação, apenas os pods do sistema. Para verificar se o nó master está com taints, execute o comando abaixo: 42 | 43 | ```bash 44 | kubectl describe nodes | grep -i taints 45 | ``` 46 | 47 | Para remover o taint do nó master, execute o comando abaixo: 48 | 49 | ```bash 50 | kubectl taint nodes node-role.kubernetes.io/control-plane:NoSchedule 51 | ``` 52 | -------------------------------------------------------------------------------- /docs/k8s/day-5/README.md: -------------------------------------------------------------------------------- 1 | # Criando um Cluster Kubernetes em Instâncias EC2 2 | 3 | Este guia detalha o processo de criação de um cluster Kubernetes em instâncias EC2 na AWS, com base nas configurações e comandos fornecidos. 4 | 5 | ## Configurações das Instâncias EC2 6 | 7 | * **Nome**: k8s 8 | * **Número de Instâncias**: 5 9 | * **Imagem da Máquina**: Ubuntu Server 22.04 LTS (HVM), SSD Volume Type 10 | * **Arquitetura**: 64 bits (x86) 11 | * **Tipo de Instância**: t2.medium 12 | * **Key Pair**: key_par_k8s 13 | * **Configuração de Armazenamento**: Volume do tipo gp3 14 | 15 | ## Configurações do Cluster Kubernetes 16 | 17 | Para criar um cluster Kubernetes usando o kubeadm, é necessário liberar algumas portas no grupo de segurança das instâncias EC2. Essas portas são essenciais para o funcionamento correto do cluster. A seguir, estão as portas que precisam ser liberadas: 18 | 19 | * **Porta 6443**: Essa porta é usada pelo servidor de API do Kubernetes para comunicação com os componentes do cluster. É necessário permitir o tráfego TCP na porta 6443 para que os nós do cluster possam se comunicar com o servidor de API. 20 | 21 | * **Portas 10250-10259**: Essas portas são usadas pelo kubelet, kube-scheduler e kube-controller-manager para comunicação interna no cluster. É necessário permitir o tráfego TCP nessas portas para que os componentes do cluster possam se comunicar entre si. 22 | 23 | * **Porta 30000-32767**: Essas portas são usadas para serviços NodePort no Kubernetes. É necessário permitir o tráfego TCP nessas portas para que os serviços NodePort possam ser acessados externamente. 24 | 25 | * **Portas 6783-6784**: Essas portas são usadas pelo Weave Net para comunicação interna no cluster. É necessário permitir o tráfego UDP nessas portas para que o Weave Net possa funcionar corretamente. 26 | 27 | * **Portas 2379-2380**: Essas portas são usadas pelo etcd para comunicação interna no cluster. É necessário permitir o tráfego TCP nessas portas para que o etcd possa funcionar corretamente. 28 | 29 | Além disso, é importante lembrar de liberar a porta 22 para permitir a conexão SSH com as instâncias EC2. 30 | 31 | Certifique-se de configurar corretamente as regras de entrada no grupo de segurança das instâncias EC2 para permitir o tráfego nessas portas. As regras de saída podem ser mantidas com as configurações padrão da AWS. 32 | TCP - Portas 10250-10259 - Security Group ID - Kubelet API, kube-scheduler e kube-controller-manager. 33 | 34 | **Regras de Saída**: 35 | 36 | Não irei específicar as regras de saída, portanto, usarão as configurações padrão da AWS. 37 | 38 | ## Conectando-se às Instâncias 39 | 40 | Para se conectar às instâncias EC2, é necessário usar a chave privada associada ao key pair usado durante a criação das instâncias. A seguir, está o comando para se conectar a uma instância EC2 usando a chave privada: 41 | 42 | ```bash 43 | sudo chmod 400 sua_chave_privada.pem 44 | ssh -i "sua_chave_privada.pem" ubuntu@ip_da_instância.compute-1.amazonaws.com 45 | ``` 46 | 47 | Substitua `sua_chave_privada.pem` pelo caminho da sua chave privada e `ip_da_instância.compute-1.amazonaws.com` pelo endereço IP público da instância EC2. 48 | 49 | Altere o hostname da máquina: 50 | 51 | ```bash 52 | sudo su - 53 | hostnamectl set-hostname k8s-1 54 | ``` 55 | 56 | ## Configurando os Nós 57 | 58 | 1. Desativando a Memória Swap: 59 | 60 | ```bash 61 | sudo swapoff -a 62 | ``` 63 | 64 | Este comando desativa a memória swap em seu sistema. No contexto do Kubernetes, a memória swap pode interferir no desempenho do sistema e causar problemas de estabilidade, portanto, é recomendado desativá-la. 65 | 66 | 2. Configurando os Módulos de Kernel: 67 | 68 | ```bash 69 | sudo nano /etc/modules-load.d/k8s.conf 70 | ``` 71 | 72 | Este comando abre o editor de texto nano para editar o arquivo k8s.conf localizado no diretório /etc/modules-load.d/. Este arquivo é usado para especificar quais módulos do kernel devem ser carregados durante a inicialização do sistema. 73 | 74 | Adicione as seguintes linhas ao arquivo: 75 | 76 | ```bash 77 | br_netfilter 78 | overlay 79 | ``` 80 | 81 | Esses módulos do kernel são necessários para o funcionamento adequado do Kubernetes. O br_netfilter é usado para configurar a ponte de rede do Docker, enquanto o overlay é usado para suportar a camada de sobreposição de contêineres. 82 | 83 | Salve e feche o arquivo. 84 | 85 | 3. Carregando os Módulos de Kernel: 86 | 87 | ```bash 88 | sudo modprobe br_netfilter 89 | sudo modprobe overlay 90 | ``` 91 | 92 | 4. Em seguida, execute: 93 | 94 | ```bash 95 | cat < -o /etc/apt/keyrings/docker.asc 134 | sudo chmod a+r /etc/apt/keyrings/docker.asc 135 | 136 | echo \ 137 | "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ 138 | $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ 139 | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null 140 | sudo apt-get update 141 | 142 | sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 143 | ``` 144 | 145 | 1. `sudo apt-get update`: Atualiza a lista de pacotes disponíveis e suas versões, mas não instala ou atualiza nenhum pacote. 146 | 147 | 2. `sudo apt-get install ca-certificates curl`: Instala os pacotes `ca-certificates` e `curl`. `ca-certificates` é usado para verificar a confiabilidade dos servidores remotos, e `curl` é usado para baixar dados de ou para um servidor. 148 | 149 | 3. `sudo install -m 0755 -d /etc/apt/keyrings`: Cria o diretório `/etc/apt/keyrings` com permissões `0755`. 150 | 151 | 4. `sudo curl -fsSL -o /etc/apt/keyrings/docker.asc`: Baixa a chave GPG do repositório Docker e a salva no arquivo `/etc/apt/keyrings/docker.asc`. 152 | 153 | 5. `sudo chmod a+r /etc/apt/keyrings/docker.asc`: Altera as permissões do arquivo `docker.asc` para que todos os usuários possam lê-lo. 154 | 155 | 6. O comando `echo` cria uma nova entrada na lista de fontes do APT para o repositório Docker. 156 | 157 | 7. `sudo apt-get update`: Novamente, atualiza a lista de pacotes disponíveis e suas versões. 158 | 159 | 8. `sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin`: Instala o Docker, o CLI do Docker, o Containerd, o plugin Docker Buildx e o plugin Docker Compose. 160 | 161 | 7. Configurando o Containerd: 162 | 163 | ```bash 164 | 165 | sudo containerd config default | sudo tee /etc/containerd/config.toml 166 | 167 | 168 | sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml 169 | 170 | sudo systemctl restart containerd 171 | sudo systemctl status containerd 172 | ``` 173 | 174 | 8. Habilitando o serviço do Kubelet: 175 | 176 | ```bash 177 | sudo systemctl enable --now kubelet 178 | systemctl status kubelet 179 | ``` 180 | 181 | **Nota**: A partir daqui, execute os comandos como `root` para evitar problemas de permissões, erros de certificado, etc. 182 | 183 | # Criando o cluster Kubernetes na versão v1.30 184 | 185 | 1. Inicializando o cluster: 186 | 187 | ```bash 188 | sudo kubeadm init --pod-network-cidr=10.10.0.0/16 --apiserver-advertise-address= 189 | 190 | # Configurando o Acesso ao Kubernetes: 191 | mkdir -p $HOME/.kube 192 | sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config 193 | sudo chown $(id -u):$(id -g) $HOME/.kube/config 194 | ``` 195 | 196 | 2. Adicionando nós workers ao cluster: 197 | 198 | ```bash 199 | sudo kubeadm join --token --discovery-token-ca-cert-hash sha256: 200 | ``` 201 | 202 | 3. Instalando o Wave Net para a rede do cluster: 203 | 204 | ```bash 205 | kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml 206 | ``` 207 | 208 | 4. Verificando o status do cluster: 209 | 210 | ```bash 211 | kubectl get nodes 212 | kubectl get pods -A 213 | ``` 214 | 215 | Agora você tem um cluster Kubernetes funcional em execução em instâncias EC2 na AWS. Você pode implantar aplicativos, serviços e recursos no cluster e começar a explorar as capacidades do Kubernetes. 216 | -------------------------------------------------------------------------------- /docs/k8s/day-6/NFS.md: -------------------------------------------------------------------------------- 1 | # Servidor NFS (Network File System) 2 | 3 | O **Servidor NFS** é uma solução que permite compartilhar sistemas de arquivos entre computadores em uma rede. Ele é amplamente usado em ambientes Linux/Unix para compartilhar diretórios e arquivos entre servidores e clientes. 4 | 5 | ## O que é um servidor NFS? 6 | 7 | - **NFS** (Network File System) é um protocolo que permite que um sistema acesse arquivos em outro sistema como se estivessem em seu próprio sistema de arquivos local. 8 | - O servidor NFS exporta (disponibiliza) diretórios ou sistemas de arquivos para os clientes NFS. 9 | - Os clientes NFS montam esses sistemas de arquivos exportados, tornando-os acessíveis como se fossem locais. 10 | 11 | ## Criando um servidor NFS 12 | 13 | Para criar um servidor NFS, siga estas etapas: 14 | 0. Crie o diretório que deseja compartilhar: 15 | 16 | ``` 17 | sudo mkdir /mnt/nfs 18 | ``` 19 | 20 | 1. **Instale o servidor NFS**: 21 | - Instale o pacote `sudo apt-get install nfs-kernel-server nfs-common` (ou similar) no seu servidor. 22 | - Inicie e habilite o serviço NFS. 23 | 24 | 2. **Configure os diretórios a serem exportados**: 25 | - Edite o arquivo `/etc/exports` para definir os diretórios que deseja compartilhar. 26 | - Exemplo de linha no arquivo `/etc/exports`: 27 | 28 | ``` 29 | /mnt/nfs *(rw,sync,no_root_squash,no_subtree_check) 30 | ``` 31 | 32 | 3. **Reinicie o serviço NFS**: 33 | - Execute o comando para aplicar as alterações: 34 | 35 | ``` 36 | sudo systemctl restart nfs-server 37 | ``` 38 | 39 | 4. **Configure as regras de firewall**: 40 | - Abra as portas necessárias (geralmente 2049 para NFS) no firewall do servidor. 41 | 42 | 5. **Monte o compartilhamento nos clientes**: 43 | - Nos clientes, use o comando `mount` para montar o compartilhamento NFS: 44 | 45 | ``` 46 | sudo mount servidor:/caminho/do/diretorio /caminho/local 47 | ``` 48 | 49 | 6. Verifique se o NFS está funcionando corretamente: 50 | - Use o comando `showmount` para verificar os compartilhamentos exportados: 51 | 52 | ``` 53 | showmount -e 54 | ``` 55 | 56 | A saída deve mostrar os diretórios exportados e os clientes que têm permissão para acessá-los. 57 | 58 | ``` 59 | Export list for ip-172-31-58-237: 60 | /mnt/nfs * 61 | ``` 62 | 63 | ## Criando um StorageClass do tipo NFS 64 | 65 | Para criar um StorageClass do tipo NFS no Kubernetes, você pode usar o seguinte exemplo: 66 | 67 | ```yaml 68 | apiVersion: storage.k8s.io/v1 69 | kind: StorageClass 70 | metadata: 71 | name: nfs 72 | provisioner: kubernetes.io/no-provisioner 73 | reclaimPolicy: Retain 74 | volumeBindingMode: WaitForFirstConsumer 75 | parameters: 76 | archiveOnDelete: "false" 77 | ``` 78 | 79 | Agora vamos criar volumes que utilizam esse StorageClass: 80 | 81 | ```yaml 82 | apiVersion: v1 83 | kind: PersistentVolume 84 | metadata: 85 | name: meu-pv-nfs 86 | labels: 87 | storage: nfs 88 | spec: 89 | capacity: 90 | storage: 1Gi 91 | accessModes: 92 | - ReadWriteOnce 93 | persistentVolumeReclaimPolicy: Retain 94 | nfs: 95 | server: 3.90.82.216 96 | path: "/mnt/nfs" 97 | storageClassName: nfs 98 | ``` 99 | 100 | Agora iremos criar um PersistentVolumeClaim (PVC) que utiliza esse PV: 101 | 102 | ```yaml 103 | apiVersion: v1 104 | kind: PersistentVolumeClaim 105 | metadata: 106 | name: meu-pvc 107 | spec: 108 | accessModes: 109 | - ReadWriteOnce 110 | resources: 111 | requests: 112 | storage: 1Gi 113 | storageClassName: nfs 114 | selector: 115 | matchLabels: 116 | storage: nfs 117 | 118 | Agora iremos criar um Pod que utiliza esse PVC: 119 | 120 | ```yaml 121 | apiVersion: v1 122 | kind: Pod 123 | metadata: 124 | name: nginx-pod 125 | spec: 126 | containers: 127 | - name: nginx 128 | image: nginx:latest 129 | ports: 130 | - containerPort: 80 131 | volumeMounts: 132 | - name: meu-pvc 133 | mountPath: /usr/share/nginx/html 134 | volumes: 135 | - name: meu-pvc 136 | persistentVolumeClaim: 137 | claimName: meu-pvc 138 | ``` 139 | 140 | Agora você tem um Pod que utiliza um volume NFS no Kubernetes. 141 | -------------------------------------------------------------------------------- /docs/k8s/day-6/README.md: -------------------------------------------------------------------------------- 1 | # Volumes no Kubernetes 2 | 3 | Os volumes no Kubernetes oferecem uma maneira de persistir e compartilhar dados entre os containers de um pod. Eles permitem que os dados sobrevivam à vida do contêiner e possam ser acessados por outros contêineres no mesmo pod. Os volumes são montados em um diretório específico dentro do sistema de arquivos do contêiner. 4 | 5 | ## O que é um StorageClass? 6 | 7 | O StorageClass é um recurso do Kubernetes que fornece uma maneira de definir diferentes classes de armazenamento para os volumes persistentes (PVs - Persistent Volumes) que serão provisionados dinamicamente. Ele atua como uma abstração entre os administradores de cluster e os usuários que solicitam armazenamento. 8 | 9 | ## Os tipos de StorageClass 10 | 11 | Existem diferentes tipos de StorageClass que podem ser definidos com base nas necessidades específicas de armazenamento de uma aplicação: 12 | 13 | ## PV (Persistent Volume) 14 | 15 | Um Persistent Volume (PV) é um recurso no Kubernetes que representa um volume de armazenamento persistente em um cluster. Ele é provisionado manualmente por um administrador do cluster ou dinamicamente por um StorageClass. Um PV tem um ciclo de vida independente do pod que o utiliza, o que significa que os dados persistem mesmo que o pod seja excluído. 16 | 17 | ## PVC (Persistent Volume Claim) 18 | 19 | Um Persistent Volume Claim (PVC) é um recurso usado por um pod para solicitar armazenamento persistente de um PV. Os PVCs são vinculados a um PV que atende aos requisitos de armazenamento definidos no PVC. Quando um PVC é criado, o Kubernetes procura um PV disponível que atenda aos critérios especificados no PVC e o vincula automaticamente. 20 | 21 | Por meio da combinação de PVs e PVCs, os desenvolvedores podem provisionar e utilizar armazenamento persistente de forma dinâmica e escalável em um cluster Kubernetes, sem a necessidade de gerenciamento manual por parte dos administradores. Isso oferece flexibilidade e eficiência na utilização de recursos de armazenamento dentro de um ambiente de contêineres. 22 | 23 | ## Políticas de retenção de volumes no Kubernetes 24 | 25 | No Kubernetes, as políticas de retenção de volumes são definidas para determinar o que acontece com um volume quando ele não é mais necessário. Atualmente, as políticas de retenção são: 26 | 27 | - **Retain**: Com essa política, quando um PersistentVolumeClaim (PVC) é excluído, o PersistentVolume (PV) correspondente não é excluído. Em vez disso, ele é movido para o estado “Released” e os dados no volume são mantidos. A recuperação dos dados é manual neste caso. 28 | 29 | - **Recycle**: Esta política está depreciada e será removida em uma futura versão do Kubernetes1. Anteriormente, ela permitia a limpeza básica do volume (por exemplo, rm -rf /thevolume/*) antes de ser reutilizado. 30 | 31 | - **Delete**: Com essa política, quando um PVC é excluído, o PV correspondente e os dados associados também são excluídos. Isso é feito automaticamente pelo cluster Kubernetes. 32 | 33 | ## Modos de acesso a volumes no Kubernetes 34 | 35 | Os três modos de acesso a volumes disponíveis no Kubernetes são: 36 | 37 | - **ReadWriteOnce (RWO)**: O volume pode ser montado como leitura-gravação por um único nó. 38 | 39 | - **ReadOnlyMany (ROX)**: O volume pode ser montado como somente leitura por muitos nós. 40 | 41 | - **ReadWriteMany (RWX)**: O volume pode ser montado como leitura-gravação por muitos nós. 42 | 43 | Esses modos de acesso determinam como o volume pode ser acessado quando é montado em um Pod. Por exemplo, se um volume for montado com o modo de acesso `ReadWriteOnce`, ele só poderá ser montado por um único nó para leitura e gravação. Se o mesmo volume for montado por outro nó, a montagem falhará. Por outro lado, um volume com o modo de acesso `ReadWriteMany` pode ser montado por vários nós para leitura e gravação simultaneamente. 44 | 45 | ## Exemplo de uso de volumes no Kubernetes 46 | 47 | A seguir, um exemplo de como definir um volume persistente em um pod no Kubernetes: 48 | 49 | ```yaml 50 | apiVersion: v1 51 | kind: Pod 52 | metadata: 53 | name: mypod 54 | spec: 55 | containers: 56 | - name: mycontainer 57 | image: nginx 58 | volumeMounts: 59 | - mountPath: /usr/share/nginx/html 60 | name: myvolume 61 | volumes: 62 | - name: myvolume 63 | persistentVolumeClaim: 64 | claimName: myclaim 65 | ``` 66 | 67 | Neste exemplo, um volume persistente chamado `myvolume` é montado no diretório `/usr/share/nginx/html` do contêiner `mycontainer`. O volume é associado a um PersistentVolumeClaim (PVC) chamado `myclaim`, que define os requisitos de armazenamento necessários para o volume. 68 | -------------------------------------------------------------------------------- /docs/k8s/day-6/files/delete.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: pv-volume 5 | spec: 6 | capacity: 7 | storage: 1Gi 8 | accessModes: 9 | - ReadWriteOnce 10 | # A política de reivindicação de volume persistente é Delete. Ou seja o volume persistente será excluído automaticamente. 11 | persistentVolumeReclaimPolicy: Delete 12 | # O tipo de armazenamento é hostPath, que é um diretório no nó do Kubernetes. 13 | hostPath: 14 | path: "/tmp/data" 15 | -------------------------------------------------------------------------------- /docs/k8s/day-6/files/pv-nfs.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: meu-pv-nfs 5 | spec: 6 | capacity: 7 | storage: 5Gi 8 | volumeMode: Filesystem 9 | accessModes: 10 | - ReadWriteMany 11 | persistentVolumeReclaimPolicy: Retain 12 | nfs: 13 | server: 14 | path: /caminho/para/compartilhamento/nfs 15 | -------------------------------------------------------------------------------- /docs/k8s/day-6/files/pvc-nfs.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: meu-pvc-nfs 5 | spec: 6 | accessModes: 7 | - ReadWriteMany 8 | storageClassName: "" 9 | volumeName: meu-pv-nfs 10 | resources: 11 | requests: 12 | storage: 5Gi 13 | -------------------------------------------------------------------------------- /docs/k8s/day-6/files/recycle.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: pv-volume 5 | spec: 6 | capacity: 7 | storage: 1Gi 8 | accessModes: 9 | - ReadWriteOnce 10 | # A política de reivindicação de volume persistente é Recycle. Ou seja o volume persistente será excluído automaticamente e o diretório será limpo. 11 | persistentVolumeReclaimPolicy: Recycle 12 | # O tipo de armazenamento é hostPath, que é um diretório no nó do Kubernetes. 13 | hostPath: 14 | path: "/tmp/data" 15 | -------------------------------------------------------------------------------- /docs/k8s/day-6/files/retain.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: pv-volume 5 | spec: 6 | capacity: 7 | storage: 1Gi 8 | accessModes: 9 | - ReadWriteOnce 10 | # A política de reivindicação de volume persistente é Retain. Ou seja o volume persistente não será excluído automaticamente. 11 | persistentVolumeReclaimPolicy: Retain 12 | # O tipo de armazenamento é hostPath, que é um diretório no nó do Kubernetes. 13 | hostPath: 14 | path: "/tmp/data" 15 | -------------------------------------------------------------------------------- /docs/k8s/day-7/README.md: -------------------------------------------------------------------------------- 1 | # O que é um StatefulSet? 2 | 3 | É um objeto da API de carga de trabalho usado para gerenciar aplicações stateful. Ele gerencia a implantação e escalonamento de um conjunto de Pods e fornece garantias sobre a ordenação e unicidade desses Pods. Como um Deployment, um StatefulSet gerencia Pods que são baseados em uma especificação de contêiner idêntica. No entanto, ao contrário de um Deployment, um StatefulSet mantém uma identidade fixa para cada um de seus Pods. Esses pods são criados a partir da mesma especificação, mas não são intercambiáveis: cada um tem um identificador persistente que mantém em qualquer reagendamento. 4 | 5 | ## Criando um StatefulSet 6 | 7 | Para criar um StatefulSet, você pode usar o comando `kubectl create ou kubectl apply`. Por exemplo, você pode criar um arquivo YAML que descreva o StatefulSet e, em seguida, aplicá-lo ao seu cluster Kubernetes. O conjunto de Pods direcionados por um StatefulSet é geralmente determinado por um seletor de rótulos. 8 | 9 | ```yaml 10 | apiVersion: apps/v1 11 | kind: StatefulSet 12 | metadata: 13 | name: nginx 14 | spec: 15 | serviceName: "nginx" 16 | replicas: 3 17 | selector: 18 | matchLabels: 19 | app: nginx 20 | template: 21 | metadata: 22 | labels: 23 | app: nginx 24 | spec: 25 | containers: 26 | - name: nginx 27 | image: nginx 28 | ports: 29 | - containerPort: 80 30 | name: web 31 | volumeMounts: 32 | - name: www 33 | mountPath: /usr/share/nginx/html 34 | volumeClaimTemplates: 35 | - metadata: 36 | name: www 37 | spec: 38 | accessModes: ["ReadWriteOnce"] 39 | resources: 40 | requests: 41 | storage: 1Gi 42 | ``` 43 | 44 | ## Removendo um StatefulSet 45 | 46 | Para remover um StatefulSet, você pode usar o comando `kubectl delete`, e especificar o StatefulSet por arquivo ou por nome. Por exemplo, `kubectl delete -f ou kubectl delete statefulsets `. 47 | 48 | # O que é um Service? 49 | 50 | Um Service no Kubernetes é um método para expor uma aplicação de rede que está sendo executada como um ou mais Pods em seu cluster. Cada objeto Service define um conjunto lógico de endpoints (geralmente esses endpoints são Pods) junto com uma política sobre como tornar esses pods acessíveis. 51 | 52 | ## Tipos de Service 53 | 54 | - **ClusterIP (padrão)**: Expõe o serviço sob um endereço IP interno no cluster. 55 | 56 | - **NodePort**: Expõe o serviço na mesma porta em cada nó selecionado no cluster usando NAT. 57 | 58 | - **LoadBalancer**: Cria um balanceador de carga externo no provedor de nuvem atual (se suportado) e atribui um endereço IP fixo e externo para o serviço. 59 | 60 | - **ExternalName**: Mapeia o Service para o conteúdo do campo externalName (por exemplo, foo.bar.example.com), retornando um registro DNS do tipo CNAME com o seu valor. 61 | 62 | ## Criando um Headless Service 63 | 64 | Um serviço headless no Kubernetes é um tipo de serviço que não tem um endereço IP de cluster atribuído. Para definir um serviço headless, definimos o campo spec.clusterIP como None em sua definição de recurso. Quando resolvemos o nome de domínio de um serviço típico, o DNS retorna um único endereço IP, que é o IP do cluster do serviço atribuído pelo plano de controle. No entanto, uma consulta DNS do nome de um serviço headless retorna uma lista de endereços IP que pertencem aos pods de backup. 65 | 66 | ```yaml 67 | apiVersion: v1 68 | kind: Service 69 | metadata: 70 | name: nginx 71 | labels: 72 | app: nginx 73 | spec: 74 | ports: 75 | - port: 80 76 | name: web 77 | clusterIP: None # Define o serviço como headless 78 | selector: 79 | app: nginx 80 | ``` 81 | 82 | Você também pode criar services pela linha de comando, por exemplo: 83 | 84 | Um serviço NodePort: 85 | 86 | ```bash 87 | kubectl expose deployment nginx --port=80 --type=NodePort 88 | ``` 89 | 90 | Um serviço LoadBalancer: 91 | 92 | ```bash 93 | kubectl expose deployment nginx --port=80 --type=LoadBalancer 94 | ``` 95 | 96 | Um serviço ClusterIP: 97 | 98 | ```bash 99 | kubectl expose deployment nginx --port=80 --type=ClusterIP 100 | ``` 101 | 102 | ### Extra 103 | 104 | Lembrando que é necessário ter o eksctl instalado na máquina. 105 | Lembre-se de configurar o AWS CLI antes de criar o cluster. 106 | 107 | Criando um cluster EKS com o eksctl: 108 | 109 | ```bash 110 | eksctl create cluster --name nataliagranato --version 1.29 --region=us-east-1 --nodegroup-name=granato --node-type=t3.medium --nodes=2 --nodes-min=1 --nodes-max=3 --managed 111 | ``` 112 | 113 | ## Criando um service expondo um outro service 114 | 115 | Para criar um service que exponha um outro service, você pode usar o comando `kubectl expose`. Por exemplo, você pode criar um service que exponha um outro service com o comando `kubectl expose service --name= --port= --target-port= --type=`. 116 | 117 | ```bash 118 | kubectl expose service nginx --name=nginx-service --port=80 --target-port=80 --type=NodePort 119 | ``` 120 | 121 | Isso é útil para realizar testes de conectividade entre serviços. 122 | -------------------------------------------------------------------------------- /docs/k8s/day-7/files/nginx-clusterip.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx 5 | labels: 6 | app: nginx 7 | spec: 8 | ports: 9 | - port: 80 10 | targetPort: 80 11 | selector: 12 | app: nginx 13 | type: ClusterIP 14 | -------------------------------------------------------------------------------- /docs/k8s/day-7/files/nginx-headless-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx 5 | labels: 6 | app: nginx 7 | spec: 8 | ports: 9 | - port: 80 10 | name: web 11 | clusterIP: None # Define o serviço como headless 12 | selector: 13 | app: nginx 14 | -------------------------------------------------------------------------------- /docs/k8s/day-7/files/nginx-lb.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx 5 | labels: 6 | app: nginx 7 | spec: 8 | ports: 9 | - port: 80 10 | targetPort: 80 11 | selector: 12 | app: nginx 13 | type: LoadBalancer 14 | -------------------------------------------------------------------------------- /docs/k8s/day-7/files/nginx-nodeport.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx 5 | labels: 6 | app: nginx 7 | spec: 8 | ports: 9 | - port: 80 10 | targetPort: 80 11 | nodePort: 30080 12 | selector: 13 | app: nginx 14 | type: NodePort 15 | -------------------------------------------------------------------------------- /docs/k8s/day-7/files/nginx-statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: nginx 5 | spec: 6 | serviceName: "nginx" 7 | replicas: 3 8 | selector: 9 | matchLabels: 10 | app: nginx 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx 19 | ports: 20 | - containerPort: 80 21 | name: web 22 | volumeMounts: 23 | - name: www 24 | mountPath: /usr/share/nginx/html 25 | volumeClaimTemplates: 26 | - metadata: 27 | name: www 28 | spec: 29 | accessModes: ["ReadWriteOnce"] 30 | resources: 31 | requests: 32 | storage: 1Gi 33 | -------------------------------------------------------------------------------- /docs/k8s/day-8/README.md: -------------------------------------------------------------------------------- 1 | # Secrets do Kubernetes 2 | 3 | ## O que são as Secrets do Kubernetes? 4 | 5 | Secrets do Kubernetes são objetos que permitem armazenar e gerenciar informações sensíveis, como senhas, tokens OAuth, chaves ssh e etc. Ao usar Secrets, você pode controlar o modo de uso de informações sensíveis em um ambiente de aplicativo, sem incluí-las no aplicativo ou na imagem do contêiner. 6 | 7 | ## Conhecendo todos os tipos de Secrets e o que é a codificação base64 8 | 9 | Existem vários tipos de Secrets que você pode criar, como: 10 | 11 | - **Opaque**: é o tipo padrão quando nada é especificado. Opaque é usado para armazenar informações arbitrárias, representadas como um mapa de strings para bytes. 12 | - **kubernetes.io/service-account-token**: contém um token que identifica uma conta de serviço. 13 | - **kubernetes.io/dockercfg**: contém um arquivo de configuração que pode ser usado para autenticar a um registro de contêiner. 14 | - **kubernetes.io/dockerconfigjson**: é uma versão do dockercfg que permite a configuração de vários registros de contêineres. 15 | - **kubernetes.io/basic-auth**: contém dados necessários para a autenticação básica. 16 | - **kubernetes.io/ssh-auth**: contém dados necessários para a autenticação SSH. 17 | - **kubernetes.io/tls**: contém informações que podem ser usadas para realizar uma resposta de desafio TLS. 18 | 19 | A codificação base64 é um esquema de codificação binário para texto que é usado quando há uma necessidade de codificar dados binários, especialmente ao esses dados precisam ser armazenados e transferidos pela internet. 20 | 21 | Para codificar uma string em base64, você pode usar o comando `echo -n 'minha-string' | base64` e para decodificar uma string em base64, você pode usar o comando `echo -n 'minha-string-base64' | base64 -d`. 22 | 23 | Para decodificar uma string em base64, você pode usar o comando `echo -n 'minha-string-base64' | base64 -d`. 24 | 25 | ## Criando uma Secret do tipo Opaque 26 | 27 | Para criar uma Secret do tipo Opaque, você pode usar o comando `kubectl create secret generic minha-secret --from-literal=username=admin --from-literal=password=senha123` seguido pelo nome da Secret e os dados a serem incluídos. Por exemplo: 28 | 29 | ```yaml 30 | apiVersion: v1 31 | kind: Secret 32 | metadata: 33 | name: minha-secret 34 | type: Opaque 35 | data: 36 | username: YWRtaW4= # 'admin' codificado em base64 37 | password: c2VuaGExMjM= # 'senha123' codificado em base64 38 | ``` 39 | 40 | ## Utilizando o nosso Secret como variável de ambiente dentro do Pod 41 | 42 | Você pode usar Secrets como variáveis de ambiente dentro de um Pod adicionando-as à seção `env` ou `envFrom` da especificação do Pod. 43 | 44 | ```yaml 45 | apiVersion: v1 46 | kind: Pod 47 | metadata: 48 | name: giropops-pod 49 | spec: 50 | containers: 51 | - name: giropops-container 52 | image: nginx 53 | env: 54 | valueFrom: 55 | secretKeyRef: 56 | name: giropops-secret 57 | key: username 58 | - name: PASSWORD 59 | valueFrom: 60 | secretKeyRef: 61 | name: giropops-secret 62 | key: password 63 | ``` 64 | 65 | Para verificar se a Secret está como variável de ambiente dentro do Pod, você pode usar o comando `kubectl exec -it giropops-pod -- env` para visualizar as variáveis de ambiente do Pod. 66 | 67 | ```bash 68 | kubectl exec giropops-pod -- env 69 | ``` 70 | 71 | ## Criando uma Secret para autenticação no Docker Hub 72 | 73 | Primeiro passo é pegar o conteúdo do seu arquivo config.json e codificar em base64, e para isso você pode usar o comando base64: 74 | 75 | ```bash 76 | cat ~/.docker/config.json | base64 77 | ``` 78 | 79 | Agora crie um arquivo chamado `docker-secret.yaml` e adicione o seguinte conteúdo: 80 | 81 | ```yaml 82 | apiVersion: v1 83 | kind: Secret 84 | metadata: 85 | name: docker-hub-secret 86 | type: kubernetes.io/dockerconfigjson # tipo do Secret 87 | data: 88 | .dockerconfigjson: | # conteúdo do arquivo config.json codificado em base64 89 | QXF1aSB0ZW0gcXVlIGVzdGFyIG8gY29udGXDumRvIGRvIHNldSBjb25maWcuanNvbiwgY29pc2EgbGluZGEgZG8gSmVmaW0= 90 | ``` 91 | 92 | Para criar uma Secret para autenticação no Docker Hub, você pode usar o comando `kubectl create secret docker-registry` seguido pelo nome da Secret e as credenciais do Docker Hub. 93 | 94 | ## Criando um Secret do tipo TLS 95 | 96 | Para criar um Secret do tipo TLS, você pode usar o comando `kubectl create secret tls meu-servico-web-tls-secret --cert=certificado.crt --key=chave-privada.key` seguido sempre pelo nome da Secret e a localização dos arquivos de certificado e chave. 97 | 98 | Verificando os dados de uma Secret, você pode usar o comando `kubectl get secret meu-servico-tls-secret -o yaml` para visualizar os dados de uma Secret. 99 | 100 | Ou você pode usar o comando `openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout chave-privada.key -out certificado.crt` para criar um certificado autoassinado. 101 | 102 | Aqui está um exemplo do arquivo de configuração do nginx para utilizar tls: 103 | 104 | ```yaml 105 | http { 106 | server { 107 | listen 80; 108 | listen 443 ssl; 109 | ssl_certificate /etc/nginx/tls/certificado.crt; 110 | ssl_certificate_key /etc/nginx/tls/chave-privada.key; 111 | 112 | location / { 113 | return 200 'Hello, World!'; 114 | add_header Content-Type text/plain; 115 | } 116 | } 117 | } 118 | ``` 119 | 120 | # Criando um ConfigMap para adicionar um arquivo no Pod e configurar o SSL no Nginx 121 | 122 | Para criar um ConfigMap para adicionar um arquivo no Pod e configurar o SSL no Nginx, você pode usar o comando `kubectl create configmap nginx-config --from-file=nginx.conf` seguido pelo nome do ConfigMap e o arquivo a ser incluído. 123 | 124 | ```yaml 125 | apiVersion: v1 126 | kind: Pod 127 | metadata: 128 | name: giropops-pod 129 | labels: 130 | app: giropops-pod 131 | spec: 132 | containers: 133 | - name: giropops-container 134 | image: nginx:1.26 135 | ports: 136 | - containerPort: 80 137 | - containerPort: 443 138 | volumeMounts: 139 | - name: meu-volume 140 | mountPath: /etc/nginx/nginx.conf 141 | subPath: nginx.conf 142 | - name: nginx-tls 143 | mountPath: /etc/nginx/tls 144 | volumes: 145 | - name: nginx-config-volume 146 | configMap: 147 | name: nginx-config 148 | - name: nginx-tls 149 | secret: 150 | secretName: meu-servico-tls-secret 151 | items: 152 | - key: certificado.crt 153 | path: certificado.crt 154 | - key: chave-privada.key 155 | path: chave-privada.key 156 | ``` 157 | 158 | Recapirulando, aprendemos o que são as Secrets do Kubernetes, os tipos de Secrets e o que é a codificação base64, como criar uma Secret do tipo Opaque, como utilizar o nosso Secret como variável de ambiente dentro do Pod, como criar uma Secret para autenticação no Docker Hub, como criar um Secret do tipo TLS e como criar um ConfigMap para adicionar um arquivo no Pod e configurar o SSL no Nginx. 159 | 160 | Para realizar o passo a passo: 161 | 162 | 1. Crie o seu certificado TLS: `openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout chave-privada.key -out certificado.crt`. 163 | 164 | 2. Crie a secret do tipo TLS com o comando `kubectl create secret tls meu-servico-tls-secret --cert=certificado.crt --key=chave-privada.key`. 165 | 166 | 3. Crie o ConfigMap com o comando `kubectl create configmap nginx-config --from-file=nginx.conf`. 167 | 168 | 4. Crie o Pod com o comando `kubectl apply -f nginx-pod.yml`. 169 | 170 | 5. Crie um service para expor o Pod criado com o comando `kubectl expose pod nginx`. Liste o service com `kubectl get svc`. 171 | 172 | 6. Faça o port-forward do service para acessar o Nginx com o comando `kubectl port-forward service/nginx 4443:443`. 173 | 174 | Para testar o Nginx, acesse o endereço `https://localhost:4443` ou `https://127.0.0.1:4443` e você verá a mensagem `Bem-vindo ao Nginx!`. 175 | 176 | Você também pode utilizar o `curl -k https://localhost:4443` e verá a seguinte mensagem: 177 | 178 | Bem-vindo ao Nginx! 179 | -------------------------------------------------------------------------------- /docs/k8s/day-8/files/configmap.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: nginx-config 5 | data: 6 | nginx.conf: | 7 | events { 8 | worker_connections 1024; # Define o número máximo de conexões simultâneas 9 | } 10 | 11 | http { 12 | server { 13 | listen 80; 14 | listen 443 ssl; 15 | 16 | ssl_certificate /etc/nginx/tls/certificado.crt; 17 | ssl_certificate_key /etc/nginx/tls/chave-privada.key; 18 | 19 | location / { 20 | return 200 'Bem-vindo ao Nginx!\n'; 21 | add_header Content-Type text/plain; 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /docs/k8s/day-8/files/nginx-pod.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: giropops-pod 5 | labels: 6 | app: giropops-pod 7 | spec: 8 | containers: 9 | - name: giropops-container 10 | image: nginx:1.26 11 | ports: 12 | - containerPort: 80 13 | - containerPort: 443 14 | volumeMounts: 15 | - name: meu-volume 16 | mountPath: /etc/nginx/nginx.conf 17 | subPath: nginx.conf 18 | - name: nginx-tls 19 | mountPath: /etc/nginx/tls 20 | volumes: 21 | - name: nginx-config-volume 22 | configMap: 23 | name: nginx-config 24 | - name: nginx-tls 25 | secret: 26 | secretName: meu-servico-tls-secret 27 | items: 28 | - key: certificado.crt 29 | path: certificado.crt 30 | - key: chave-privada.key 31 | path: chave-privada.key 32 | -------------------------------------------------------------------------------- /docs/k8s/day-8/files/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; # Define o número máximo de conexões simultâneas 3 | } 4 | 5 | http { # configuração do protocolo HTTP, que é o protocolo que o Nginx vai usar 6 | server { # configuração do servidor 7 | listen 80; # porta que o Nginx vai escutar 8 | listen 443 ssl; # porta que o Nginx vai escutar para HTTPS e passando o parâmetro ssl para habilitar o HTTPS 9 | 10 | ssl_certificate /etc/nginx/tls/certificado.crt; # caminho do certificado TLS 11 | ssl_certificate_key /etc/nginx/tls/chave-privada.key; # caminho da chave privada 12 | 13 | location / { # configuração da rota / 14 | return 200 'Bem-vindo ao Nginx!\n'; # retorna o código 200 e a mensagem Bem-vindo ao Nginx! 15 | add_header Content-Type text/plain; # adiciona o header Content-Type com o valor text/plain 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /docs/k8s/day-8/files/secret.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: minha-secret 5 | type: Opaque 6 | data: 7 | username: YWRtaW4= # 'admin' codificado em base64 8 | password: c2VuaGExMjM= # 'senha123' codificado em base64 9 | -------------------------------------------------------------------------------- /docs/k8s/day-9/files/README.md: -------------------------------------------------------------------------------- 1 | # Criando um cluster eks com o eksctl 2 | 3 | Para criar um cluster EKS com o eksctl, você precisa ter o eksctl instalado, realize a instalação com o comando abaixo: 4 | 5 | ```bash 6 | curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp 7 | sudo mv /tmp/eksctl /usr/local/bin 8 | ``` 9 | 10 | Iremos precisar do AWS CLI instalado e configurado em nossa máquina. Para instalar o AWS CLI, use o comando abaixo: 11 | 12 | ```bash 13 | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" 14 | unzip awscliv2.zip 15 | sudo ./aws/install 16 | ``` 17 | 18 | Agora exporte as variáveis de ambiente com suas credenciais da AWS: 19 | 20 | ```bash 21 | export AWS_ACCESS_KEY_ID=your_access_key_id 22 | export AWS_SECRET_ACCESS_KEY=your_secret_access_key 23 | export AWS_DEFAULT_REGION=your_region 24 | ``` 25 | 26 | Para criar um cluster EKS, execute o comando abaixo: 27 | 28 | ```bash 29 | eksctl create cluster --name=nataliagranato --nodes=2 --node-type=t3.medium 30 | ``` 31 | 32 | Outra opção é criar um arquivo de configuração para o eksctl, como o exemplo abaixo: 33 | 34 | ```yaml 35 | apiVersion: eksctl.io/v1alpha5 36 | kind: ClusterConfig 37 | 38 | metadata: 39 | name: nataliagranato 40 | region: us-east-1 41 | version: "1.29" 42 | 43 | availabilityZones: ["us-east-1a", "us-east-1b", "us-east-1c"] 44 | 45 | vpc: 46 | cidr: 172.20.0.0/16 47 | clusterEndpoints: 48 | publicAccess: true 49 | privateAccess: true 50 | 51 | iam: 52 | withOIDC: true 53 | serviceAccounts: 54 | - metadata: 55 | name: s3-fullaccess 56 | attachPolicyARNs: 57 | - "arn:aws:iam::aws:policy/AmazonS3FullAccess" 58 | - metadata: 59 | name: aws-load-balancer-controller 60 | namespace: kube-system 61 | wellKnownPolicies: 62 | awsLoadBalancerController: true 63 | - metadata: 64 | name: external-dns 65 | namespace: kube-system 66 | wellKnownPolicies: 67 | externalDNS: true 68 | - metadata: 69 | name: cert-manager 70 | namespace: cert-manager 71 | wellKnownPolicies: 72 | certManager: true 73 | - metadata: 74 | name: cluster-autoscaler 75 | namespace: kube-system 76 | wellKnownPolicies: 77 | autoScaler: true 78 | ``` 79 | 80 | Para criar o cluster com o arquivo de configuração, execute o comando abaixo: 81 | 82 | ```bash 83 | eksctl create cluster -f cluster.yaml 84 | ``` 85 | 86 | Crie um nodegroup com o comando abaixo: 87 | 88 | ```bash 89 | eksctl create nodegroup --cluster=nataliagranato --region=us-east-1 --name=ng-1 --node-type=t3.medium --nodes=2 --nodes-min=2 --nodes-max=4 90 | ``` 91 | 92 | ou com o arquivo de configuração: 93 | 94 | ```yaml 95 | apiVersion: eksctl.io/v1alpha5 96 | kind: ClusterConfig 97 | 98 | metadata: 99 | name: nataliagranato 100 | region: us-east-1 101 | version: "1.29" 102 | 103 | managedNodeGroups: 104 | - name: ng-ondemand 105 | instanceTypes: ["m6a.xlarge"] 106 | spot: false 107 | privateNetworking: true 108 | minSize: 1 109 | maxSize: 1 110 | desiredCapacity: 1 111 | volumeSize: 50 112 | volumeType: gp3 113 | updateConfig: 114 | maxUnavailablePercentage: 30 115 | availabilityZones: ["us-east-1a"] 116 | ssh: 117 | allow: false 118 | labels: 119 | node_group: ng-ondemand 120 | tags: 121 | nodegroup-role: ng-ondemand 122 | k8s.io/cluster-autoscaler/enabled: "true" 123 | k8s.io/cluster-autoscaler/cco-hml: "owned" 124 | 125 | iam: 126 | withAddonPolicies: 127 | externalDNS: true 128 | certManager: true 129 | imageBuilder: true 130 | albIngress: true 131 | autoScaler: true 132 | ebs: true 133 | efs: true 134 | ``` 135 | 136 | Para criar o nodegroup com o arquivo de configuração, execute o comando abaixo: 137 | 138 | ```bash 139 | eksctl create nodegroup -f nodegroup.yaml 140 | ``` 141 | 142 | Para deletar o cluster, execute o comando abaixo: 143 | 144 | ```bash 145 | eksctl delete cluster --name=nataliagranato 146 | ``` 147 | 148 | ## Prometheus Operator e o Kube-Prometheus 149 | 150 | O Prometheus Operator é um projeto que facilita a configuração e o gerenciamento do Prometheus e de seus componentes relacionados. O Kube-Prometheus é um conjunto de arquivos de configuração e scripts que facilitam a instalação do Prometheus Operator e de seus componentes relacionados em um cluster Kubernetes. 151 | 152 | ## Instalando o Kube-Prometheus 153 | 154 | Realize o clone do repositório do Kube-Prometheus: 155 | 156 | ```bash 157 | git clone https://github.com/prometheus-operator/kube-prometheus 158 | cd kube-prometheus 159 | kubectl create -f manifests/setup 160 | kubectl create -f manifests/ 161 | ``` 162 | 163 | Caso enfrente o problema `spec: failed to generate spec: path "/sys" is mounted on "/sys" but it is not a shared or slave mount` no daemonset node-exporter, use o manifesto abaixo para corrigir: 164 | 165 | ```yaml 166 | apiVersion: apps/v1 167 | kind: DaemonSet 168 | metadata: 169 | labels: 170 | app.kubernetes.io/component: exporter 171 | app.kubernetes.io/name: node-exporter 172 | app.kubernetes.io/part-of: kube-prometheus 173 | app.kubernetes.io/version: 1.8.1 174 | name: node-exporter 175 | namespace: monitoring 176 | spec: 177 | selector: 178 | matchLabels: 179 | app.kubernetes.io/component: exporter 180 | app.kubernetes.io/name: node-exporter 181 | app.kubernetes.io/part-of: kube-prometheus 182 | template: 183 | metadata: 184 | annotations: 185 | kubectl.kubernetes.io/default-container: node-exporter 186 | labels: 187 | app.kubernetes.io/component: exporter 188 | app.kubernetes.io/name: node-exporter 189 | app.kubernetes.io/part-of: kube-prometheus 190 | app.kubernetes.io/version: 1.8.1 191 | spec: 192 | automountServiceAccountToken: true 193 | containers: 194 | - args: 195 | - --web.listen-address=127.0.0.1:9100 196 | - --path.sysfs=/host/sys 197 | - --path.rootfs=/host/root 198 | - --path.udev.data=/host/root/run/udev/data 199 | - --no-collector.wifi 200 | - --no-collector.hwmon 201 | - --no-collector.btrfs 202 | - --collector.filesystem.mount-points-exclude=^/(dev|proc|sys|run/k3s/containerd/.+|var/lib/docker/.+|var/lib/kubelet/pods/.+)($|/) 203 | - --collector.netclass.ignored-devices=^(veth.*|[a-f0-9]{15})$ 204 | - --collector.netdev.device-exclude=^(veth.*|[a-f0-9]{15})$ 205 | image: quay.io/prometheus/node-exporter:v1.8.1 206 | name: node-exporter 207 | resources: 208 | limits: 209 | cpu: 250m 210 | memory: 180Mi 211 | requests: 212 | cpu: 102m 213 | memory: 180Mi 214 | securityContext: 215 | allowPrivilegeEscalation: false 216 | capabilities: 217 | add: 218 | - SYS_TIME 219 | drop: 220 | - ALL 221 | readOnlyRootFilesystem: true 222 | volumeMounts: 223 | - mountPath: /host/sys 224 | name: sys 225 | readOnly: true 226 | - mountPath: /host/root 227 | mountPropagation: HostToContainer 228 | name: root 229 | readOnly: true 230 | - args: 231 | - --secure-listen-address=[$(IP)]:9100 232 | - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 233 | - --upstream=http://127.0.0.1:9100/ 234 | env: 235 | - name: IP 236 | valueFrom: 237 | fieldRef: 238 | fieldPath: status.podIP 239 | image: quay.io/brancz/kube-rbac-proxy:v0.18.0 240 | name: kube-rbac-proxy 241 | ports: 242 | - containerPort: 9100 243 | hostPort: 9100 244 | name: https 245 | resources: 246 | limits: 247 | cpu: 20m 248 | memory: 40Mi 249 | requests: 250 | cpu: 10m 251 | memory: 20Mi 252 | securityContext: 253 | allowPrivilegeEscalation: false 254 | capabilities: 255 | drop: 256 | - ALL 257 | readOnlyRootFilesystem: true 258 | runAsGroup: 65532 259 | runAsNonRoot: true 260 | runAsUser: 65532 261 | seccompProfile: 262 | type: RuntimeDefault 263 | hostNetwork: true 264 | hostPID: true 265 | nodeSelector: 266 | kubernetes.io/os: linux 267 | priorityClassName: system-cluster-critical 268 | securityContext: 269 | runAsGroup: 65534 270 | runAsNonRoot: true 271 | runAsUser: 65534 272 | serviceAccountName: node-exporter 273 | tolerations: 274 | - operator: Exists 275 | volumes: 276 | - hostPath: 277 | path: /sys 278 | name: sys 279 | - hostPath: 280 | path: / 281 | name: root 282 | updateStrategy: 283 | rollingUpdate: 284 | maxUnavailable: 10% 285 | type: RollingUpdate 286 | ``` 287 | 288 | A `mountPropagation: HostToContainer` foi retirada do volume `/sys` e mantida no volume `/root`. 289 | 290 | ## Acessando o Grafana e os Dashboards 291 | 292 | Para acessar o Grafana utilize o `kubectl port-forward`: 293 | 294 | ```bash 295 | kubectl port-forward -n monitoring svc/grafana 3000:3000 296 | ``` 297 | 298 | Acesse o Grafana em `http://localhost:3000` com o usuário `admin` e a senha `admin`. Será solicitado a troca de senha. 299 | 300 | ### Acessando o Prometheus e o Alertmanager 301 | 302 | Para acessar o Prometheus e o Alertmanager, utilize o `kubectl port-forward`: 303 | 304 | ```bash 305 | kubectl port-forward -n monitoring svc/prometheus-k8s 9090:9090 306 | kubectl port-forward -n monitoring svc/alertmanager-main 9093:9093 307 | ``` 308 | 309 | ### O que são os monitores do Prometheus? 310 | 311 | Os monitores do Prometheus são arquivos de configuração que definem o que e como coletar métricas de um serviço ou aplicação. Eles são escritos em uma linguagem de consulta chamada PromQL. 312 | 313 | ### O que são os alertas do Alertmanager? 314 | 315 | A principal função do Alertmanager é receber alertas do Prometheus e enviá-los para os destinatários corretos. Os alertas são definidos em arquivos de configuração chamados de regras de alerta. As regras de alerta são escritas em uma linguagem de consulta chamada PromQL. É possível definir regras de alerta para qualquer métrica coletada pelo Prometheus e integrar com diversos serviços de notificação. 316 | --------------------------------------------------------------------------------