├── .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 | 
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 | 
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 |
--------------------------------------------------------------------------------