├── .github └── workflows │ └── deploy.yml ├── .github └── workflows │ └── deploy.yml ├── .gitignore ├── CNAME ├── LANGS.md ├── LICENSE ├── README.md ├── en ├── CONTRIBUTING.md ├── README.md ├── SUMMARY.md ├── day_five │ └── descomplicando_kubernetes.md ├── day_four │ └── descomplicando_kubernetes.md ├── day_one │ └── descomplicando_kubernetes.md ├── day_six │ └── descomplicando_kubernetes.md ├── day_three │ └── descomplicando_kubernetes.md ├── day_two │ └── descomplicando_kubernetes.md └── extras │ ├── cloud-providers │ ├── azure │ │ ├── aks-helloworld-one.yaml │ │ ├── aks-helloworld-two.yaml │ │ └── hello-world-ingress.yaml │ └── cloud-providers.md │ ├── exame_tips.md │ └── pod_security_policy.md ├── es ├── CONTRIBUTING.md ├── README.md ├── SUMMARY.md ├── day-1 │ ├── README.md │ └── files │ │ └── desafio │ │ └── mi-primer-pod.yaml ├── day-10 │ └── README.md ├── day-11 │ └── README.md ├── day-12 │ └── README.md ├── day-13 │ └── README.md ├── day-14 │ ├── README.md │ └── images │ │ ├── image-1.png │ │ ├── image-2.png │ │ └── image-3.png ├── day-15 │ └── README.md ├── day-2 │ └── README.md ├── day-3 │ └── README.md ├── day-4 │ ├── README.md │ ├── files │ │ ├── nginx-deployment.yaml │ │ ├── nginx-liveness.yaml │ │ ├── nginx-readiness.yaml │ │ ├── nginx-replicaset.yaml │ │ ├── nginx-startup.yaml │ │ ├── nginx-todas-probes.yaml │ │ └── node-exporter-daemonset.yaml │ ├── nginx-daemonset.yaml │ ├── nginx-deployment.yaml │ └── nginx-replicaset.yaml ├── day-5 │ └── README.md ├── day-6 │ ├── README.md │ └── files │ │ ├── giropops-senhas-deployment.yaml │ │ ├── giropops-senhas-service.yaml │ │ ├── pod-emptydir.yaml │ │ ├── pod.yaml │ │ ├── pv-nfs.yaml │ │ ├── pv.yaml │ │ ├── pvc.yaml │ │ ├── storageclass-nfs.yaml │ │ └── storageclass.yaml ├── day-7 │ ├── README.md │ └── files │ │ ├── headless-service.yaml │ │ ├── nginx-clusterip-svc.yaml │ │ ├── nginx-deployment.yaml │ │ ├── nginx-loadbalancer-svc.yaml │ │ ├── nginx-nodeport-svc.yaml │ │ └── nginx-statefulset.yaml ├── day-8 │ └── README.md └── day-9 │ └── README.md ├── images ├── KeyValue.png ├── kubernetes_architecture.png ├── kubernetes_commands.png ├── logo-LINUXtips-2021.png └── relational-database-chart.jpg ├── local-cluster-vm ├── .vagrant │ ├── cluster-tools.sh │ ├── etc │ │ └── docker │ │ │ └── deamon.json │ ├── k8s-init-cluster.sh │ └── runtime-container-config.sh ├── content.md ├── token-vm-k8s │ └── .token_join └── vagrantfile ├── package.json ├── pt ├── CONTRIBUTING.md ├── README.md ├── SUMMARY.md ├── day-1 │ ├── README.md │ └── files │ │ └── desafio │ │ └── meu-primeiro-pod.yaml ├── day-10 │ ├── README.md │ └── files │ │ ├── app-deployment.yaml │ │ ├── cluster-issuer-prod.yaml │ │ ├── ingress.yaml │ │ ├── ingress2.yaml │ │ ├── ingress3.yaml │ │ ├── ingress4.yaml │ │ ├── ingress5.yaml │ │ ├── ingress6.yaml │ │ └── staging-issuer.yaml ├── day-11 │ └── README.md ├── day-12 │ └── README.md ├── day-13 │ └── README.md ├── day-14 │ ├── README.md │ └── images │ │ ├── image-1.png │ │ ├── image-2.png │ │ └── image-3.png ├── day-15 │ └── README.md ├── day-16 │ ├── README.md │ ├── files │ │ ├── README.md │ │ └── charts │ │ │ └── giropops-senhas │ │ │ ├── .helmignore │ │ │ ├── Chart.yaml │ │ │ ├── templates │ │ │ ├── _helpers.tpl │ │ │ ├── configmap-db.yaml │ │ │ ├── configmap-observability.yaml │ │ │ ├── deployments.yaml │ │ │ └── services.yaml │ │ │ └── values.yaml │ └── images │ │ └── github-pages.png ├── day-2 │ └── README.md ├── day-3 │ └── README.md ├── day-4 │ ├── README.md │ ├── files │ │ ├── nginx-deployment.yaml │ │ ├── nginx-liveness.yaml │ │ ├── nginx-readiness.yaml │ │ ├── nginx-replicaset.yaml │ │ ├── nginx-startup.yaml │ │ ├── nginx-todas-probes.yaml │ │ └── node-exporter-daemonset.yaml │ ├── nginx-daemonset.yaml │ ├── nginx-deployment.yaml │ └── nginx-replicaset.yaml ├── day-5 │ └── README.md ├── day-6 │ ├── README.md │ └── files │ │ ├── giropops-senhas-deployment.yaml │ │ ├── giropops-senhas-service.yaml │ │ ├── pod.yaml │ │ ├── pv-nfs.yaml │ │ ├── pv.yaml │ │ ├── pvc.yaml │ │ ├── storageclass-nfs.yaml │ │ └── storageclass.yaml ├── day-7 │ ├── README.md │ └── files │ │ ├── headless-service.yaml │ │ ├── nginx-clusterip-svc.yaml │ │ ├── nginx-deployment.yaml │ │ ├── nginx-loadbalancer-svc.yaml │ │ ├── nginx-nodeport-svc.yaml │ │ └── nginx-statefulset.yaml ├── day-8 │ └── README.md └── day-9 │ ├── README.md │ └── files │ ├── app-deployment.yaml │ ├── app-service.yaml │ ├── ingress-1.yaml │ ├── ingress-2.yaml │ ├── ingress-3.yaml │ ├── ingress-4.yaml │ ├── ingress-5.yaml │ ├── ingress-6.yaml │ ├── ingress-7.yaml │ ├── kind-config.yaml │ ├── redis-deployment.yaml │ └── redis-service.yaml ├── styles └── website.css └── yarn.lock / .github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ main ] 7 | jobs: 8 | build-and-deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | with: 14 | persist-credentials: false 15 | - name: Install the dependencies 16 | run: npm install 17 | - name: Build docs 18 | run: npx honkit build 19 | - name: Deploy 20 | uses: JamesIves/github-pages-deploy-action@releases/v3 21 | with: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | BRANCH: gh-pages 24 | FOLDER: _book 25 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ main ] 7 | jobs: 8 | build-and-deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | with: 14 | persist-credentials: false 15 | - name: Install the dependencies 16 | run: npm install 17 | - name: Build docs 18 | run: npx honkit build 19 | - name: Deploy 20 | uses: JamesIves/github-pages-deploy-action@releases/v3 21 | with: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | BRANCH: gh-pages 24 | FOLDER: _book 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /_book/ 2 | /node_modules/ 3 | /book.pdf 4 | /book.mobi 5 | /book.epub 6 | .vscode 7 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | livro.descomplicandokubernetes.com.br -------------------------------------------------------------------------------- /LANGS.md: -------------------------------------------------------------------------------- 1 | # Languages 2 | 3 | * [🇧🇷 Português-brasileiro](pt/) 4 | * [🇺🇸 English (in progress)](en/) 5 | * [🇪🇸 Español (in progress)](es/) 6 | 7 | ![LINUXtips](images/logo-LINUXtips-2021.png) 8 | -------------------------------------------------------------------------------- /en/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribuindo 2 | 3 | Sua contribuição é muito bem vinda! 4 | 5 | Execute os passos a seguir sempre que desejar melhorar o conteúdo deste repositório. 6 | 7 | * Instale os seguintes pacotes: ``git`` e um editor de texto de sua preferência. 8 | * Crie um fork neste repositório. Veja este tutorial: https://help.github.com/en/github/getting-started-with-github/fork-a-repo 9 | * Clone o repositório resultante do fork para o seu computador. 10 | * Adicione a URL do repositório de origem com o comando a seguir. 11 | 12 | ``` 13 | git remote -v 14 | git remote add upstream https://github.com/badtuxx/DescomplicandoKubernetes 15 | git remote -v 16 | ``` 17 | 18 | * Crie uma branch usando o padrão: 19 | 20 | ``` 21 | git checkout -b BRANCH_NAME 22 | ``` 23 | 24 | * Certifique-se de que está na branch correta, usando o comando a seguir. 25 | 26 | ``` 27 | git branch 28 | ``` 29 | 30 | * A branch em uso contém o '*' antes do nome. 31 | * Faça as alterações necessárias. 32 | * Teste suas alterações (se necessário). 33 | * Commit as suas alterações na branch recém criada, de preferência faça um commit para cada arquivo editado/criado. 34 | * Envie os commits para o repositório remoto com o comando: 35 | 36 | ```git push --set-upstream origin BRANCH_NAME```. 37 | 38 | * Crie um Pull Request (PR) para a branch `main` do repositório original. Veja este [tutorial](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork) 39 | * Atualize o conteúdo com as sugestões do revisor (se necessário). 40 | * Depois de aprovado e realizado o merge do seu PR, atualize as mudanças no seu repositório local com os comandos a seguir. 41 | 42 | ```bash 43 | git checkout main 44 | git pull upstream main 45 | ``` 46 | 47 | * Remova a branch local após a aprovação e merge do seu PR, usando o comando: 48 | 49 | ``` 50 | git branch -d BRANCH_NAME 51 | ``` 52 | 53 | * Atualize a branch ``main`` do seu repositório local. 54 | 55 | ``` 56 | git push origin main 57 | ``` 58 | 59 | * Envie a exclusão da branch local para o seu repositório no GitHub com o comando: 60 | 61 | ``` 62 | git push --delete origin BRANCH_NAME 63 | ``` 64 | 65 | * Para manter seu fork em sincronia com o repositório original, execute estes comandos: 66 | 67 | ``` 68 | git pull upstream main 69 | git push origin main 70 | ``` 71 | 72 | Referência: 73 | * https://blog.scottlowe.org/2015/01/27/using-fork-branch-git-workflow/ 74 | 75 | # Dica 76 | 77 | **Você pode usar o editor de texto de sua preferência e que se sinta mais confortável de usar.** 78 | 79 | Mas o VSCode (https://code.visualstudio.com), combinado com os plugins a seguir, auxilia o processo de edição/revisão, principalmente permitindo a pré-visualização do conteúdo antes do commit, analisando a sintaxe do Markdown e gerando o sumário automático, à medida que os títulos das seções vão sendo criados/alterados. 80 | 81 | * Markdown-lint: https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint 82 | * Markdown-toc: https://marketplace.visualstudio.com/items?itemName=AlanWalk.markdown-toc 83 | * Markdown-all-in-one: https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one 84 | * YAML: https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml 85 | * Helm-intellisense: https://marketplace.visualstudio.com/items?itemName=Tim-Koehler.helm-intellisense 86 | * GitLens: https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens 87 | * Themes for VSCode: 88 | * https://code.visualstudio.com/docs/getstarted/themes 89 | * https://dev.to/thegeoffstevens/50-vs-code-themes-for-2020-45cc 90 | * https://vscodethemes.com/ -------------------------------------------------------------------------------- /en/README.md: -------------------------------------------------------------------------------- 1 | # Making Kubernetes uncomplicated 2 | 3 | The content of this repository was initially private and belonged to [LinuxTips](https://www.linuxtips.io), where only students of the course [Uncomplicating Kubernetes](https://www.linuxtips.io/product-page/uncomplicating-it-kubernetes) had access. 4 | 5 | Due to the [Coronavirus (COVID-19)](https://coronavirus.jhu.edu/map.html) and inspired by the [Foca GNU/Linux Guide](https://guiafoca.org), from [Gleydson Mazioli da Silva](https://twitter.com/gleydsonmazioli), and [Jeferson Fernando](https://twitter.com/badtux_) released public access to this repository as a way to help fight the pandemic by encouraging people staying at home acquiring knowledge and improving themselves in the profession to be able to contribute in the workplace or even prepare for new opportunities. 6 | 7 | The content of this material is divided into 6 parts (day_one to day_six) to facilitate learning. The idea is for the student to focus on learning in stages and for that reason we recommend that he move to the next part only when he is totally comfortable with the current content. 8 | 9 | In this material you will have contact with contents that cover from beginner to advanced level on Kubernetes, and now that it has become open, with the help of everyone we will build the largest and most complete material on Kubernetes in the world. 10 | 11 | In the future, the content of this repository will become a book, with the name of all the people who contributed to the project. The amount that will be collected with the sale of the book, will be destined for some organization that helps the bankrupt and people with financial problems and/or problems with access to information, such as the [Bienal da Quebrada](https://twitter.com/bienalquebrada). 12 | 13 | We count on your help to make this material even more complete, collaborate! To contribute to improvements in content, follow the instructions in this [tutorial](CONTRIBUTING.md). 14 | 15 | Watch videos on Kubernetes and even other cool topics on the LinuxTips channel. 16 | 17 | * https://www.youtube.com/user/linuxtipscanal/videos 18 | * https://www.youtube.com/user/linuxtipscanal/playlists 19 | -------------------------------------------------------------------------------- /en/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | ## Sobre 4 | * [Introdução](README.md) 5 | 6 | ## Capítulos 7 | * [Descomplicando Kubernetes dia 1](day_one/descomplicando_kubernetes.md) 8 | * [Descomplicando Kubernetes dia 2](day_two/descomplicando_kubernetes.md) 9 | * [Descomplicando Kubernetes dia 3](day_three/descomplicando_kubernetes.md) 10 | * [Descomplicando Kubernetes dia 4](day_four/descomplicando_kubernetes.md) 11 | * [Descomplicando Kubernetes dia 5](day_five/descomplicando_kubernetes.md) 12 | * [Descomplicando Kubernetes dia 6](day_six/descomplicando_kubernetes.md) 13 | 14 | ## Extras 15 | * [Cloud providers](extras/cloud-providers/cloud-providers.md) 16 | * [Dicas para o exame](extras/exame_tips.md) 17 | * [Pod security policy](extras/pod_security_policy.md) 18 | 19 | ## Contribuir 20 | * [Como ajudar](CONTRIBUTING.md) -------------------------------------------------------------------------------- /en/day_five/descomplicando_kubernetes.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/en/day_five/descomplicando_kubernetes.md -------------------------------------------------------------------------------- /en/day_four/descomplicando_kubernetes.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/en/day_four/descomplicando_kubernetes.md -------------------------------------------------------------------------------- /en/day_one/descomplicando_kubernetes.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/en/day_one/descomplicando_kubernetes.md -------------------------------------------------------------------------------- /en/day_six/descomplicando_kubernetes.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/en/day_six/descomplicando_kubernetes.md -------------------------------------------------------------------------------- /en/day_three/descomplicando_kubernetes.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/en/day_three/descomplicando_kubernetes.md -------------------------------------------------------------------------------- /en/day_two/descomplicando_kubernetes.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/en/day_two/descomplicando_kubernetes.md -------------------------------------------------------------------------------- /en/extras/cloud-providers/azure/aks-helloworld-one.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: aks-helloworld-one 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: aks-helloworld-one 10 | template: 11 | metadata: 12 | labels: 13 | app: aks-helloworld-one 14 | spec: 15 | containers: 16 | - name: aks-helloworld-one 17 | image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 18 | ports: 19 | - containerPort: 80 20 | env: 21 | - name: TITLE 22 | value: "Welcome to Azure Kubernetes Service (AKS)" 23 | --- 24 | apiVersion: v1 25 | kind: Service 26 | metadata: 27 | name: aks-helloworld-one 28 | spec: 29 | type: ClusterIP 30 | ports: 31 | - port: 80 32 | selector: 33 | app: aks-helloworld-one 34 | -------------------------------------------------------------------------------- /en/extras/cloud-providers/azure/aks-helloworld-two.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: aks-helloworld-two 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: aks-helloworld-two 10 | template: 11 | metadata: 12 | labels: 13 | app: aks-helloworld-two 14 | spec: 15 | containers: 16 | - name: aks-helloworld-two 17 | image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 18 | ports: 19 | - containerPort: 80 20 | env: 21 | - name: TITLE 22 | value: "AKS Ingress Demo" 23 | --- 24 | apiVersion: v1 25 | kind: Service 26 | metadata: 27 | name: aks-helloworld-two 28 | spec: 29 | type: ClusterIP 30 | ports: 31 | - port: 80 32 | selector: 33 | app: aks-helloworld-two 34 | -------------------------------------------------------------------------------- /en/extras/cloud-providers/azure/hello-world-ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: hello-world-ingress 5 | annotations: 6 | kubernetes.io/ingress.class: nginx 7 | nginx.ingress.kubernetes.io/rewrite-target: /$1 8 | nginx.ingress.kubernetes.io/use-regex: "true" 9 | cert-manager.io/cluster-issuer: letsencrypt 10 | spec: 11 | tls: 12 | - hosts: 13 | - giropops-live.eastus.cloudapp.azure.com 14 | secretName: tls-secret 15 | rules: 16 | - host: giropops-live.eastus.cloudapp.azure.com 17 | http: 18 | paths: 19 | - backend: 20 | serviceName: aks-helloworld-one 21 | servicePort: 80 22 | path: /hello-world-one(/|$)(.*) 23 | - backend: 24 | serviceName: aks-helloworld-two 25 | servicePort: 80 26 | path: /hello-world-two(/|$)(.*) 27 | - backend: 28 | serviceName: aks-helloworld-one 29 | servicePort: 80 30 | path: /(.*) 31 | --- 32 | apiVersion: networking.k8s.io/v1beta1 33 | kind: Ingress 34 | metadata: 35 | name: hello-world-ingress-static 36 | annotations: 37 | kubernetes.io/ingress.class: nginx 38 | nginx.ingress.kubernetes.io/rewrite-target: /static/$2 39 | nginx.ingress.kubernetes.io/use-regex: "true" 40 | cert-manager.io/cluster-issuer: letsencrypt 41 | spec: 42 | tls: 43 | - hosts: 44 | - giropops-live.eastus.cloudapp.azure.com 45 | secretName: tls-secret 46 | rules: 47 | - host: giropops-live.eastus.cloudapp.azure.com 48 | http: 49 | paths: 50 | - backend: 51 | serviceName: aks-helloworld-one 52 | servicePort: 80 53 | path: /static(/|$)(.*) 54 | -------------------------------------------------------------------------------- /en/extras/cloud-providers/cloud-providers.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/en/extras/cloud-providers/cloud-providers.md -------------------------------------------------------------------------------- /en/extras/exame_tips.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/en/extras/exame_tips.md -------------------------------------------------------------------------------- /en/extras/pod_security_policy.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/en/extras/pod_security_policy.md -------------------------------------------------------------------------------- /es/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribución 2 | 3 | ¡Tu contribución es muy bienvenida! 4 | 5 | Sigue los pasos a continuación siempre que desees mejorar el contenido de este repositorio. 6 | 7 | * Instala los siguientes paquetes: `git` y un editor de texto de tu preferencia. 8 | * Crea un fork de este repositorio. Consulta este tutorial: 9 | * Clona el repositorio resultante del fork en tu ordenador. 10 | * Agrega la URL del repositorio original con el siguiente comando. 11 | 12 | ```bash 13 | git remote -v 14 | git remote add upstream https://github.com/badtuxx/DescomplicandoKubernetes 15 | git remote -v 16 | ``` 17 | 18 | * Crea una rama utilizando el siguiente convención: 19 | 20 | ```bash 21 | git checkout -b NOMBRE_DE_LA_RAMA 22 | ``` 23 | 24 | * Asegúrate de que estás en la rama correcta utilizando el siguiente comando. 25 | 26 | ```bash 27 | git branch 28 | ``` 29 | 30 | * La rama en uso tendrá un '*' antes del nombre. 31 | * Realiza los cambios necesarios. 32 | * Prueba tus cambios (si es necesario). 33 | * Haz un commit de tus cambios en la rama recién creada, preferiblemente realiza un commit por cada archivo editado/creado. 34 | * Envía tus commits al repositorio remoto con el comando: 35 | 36 | ```git push --set-upstream origin NOMBRE_DE_LA_RAMA```. 37 | 38 | * Crea una solicitud de extracción (Pull Request, PR) hacia la rama `main` del repositorio original. Consulta este [tutorial](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork) 39 | * Actualiza el contenido con las sugerencias del revisor (si es necesario). 40 | * Después de que tu PR sea aprobado y se haya realizado el merge, actualiza los cambios en tu repositorio local con los siguientes comandos. 41 | 42 | ```bash 43 | git checkout main 44 | git pull upstream main 45 | ``` 46 | 47 | * Elimina la rama local después de que se apruebe y se realice el merge de tu PR, utilizando el comando: 48 | 49 | ```bash 50 | git branch -d NOMBRE_DE_LA_RAMA 51 | ``` 52 | 53 | * Actualiza la rama ``main`` de tu repositorio local. 54 | 55 | ```bash 56 | git push origin main 57 | ``` 58 | 59 | * Envía la eliminación de la rama local a tu repositorio en GitHub con el comando: 60 | 61 | ```bash 62 | git push --delete origin NOMBRE_DE_LA_RAMA 63 | ``` 64 | 65 | * Para mantener tu fork sincronizado con el repositorio original, ejecuta los siguientes comandos: 66 | 67 | ```bash 68 | git pull upstream main 69 | git push origin main 70 | ``` 71 | 72 | Referencia: 73 | 74 | * 75 | 76 | # Consejo 77 | 78 | **Puedes utilizar el editor de texto de tu preferencia y con el que te sientas más cómodo.** 79 | 80 | Sin embargo, VSCode (), combinado con los siguientes complementos, facilita el proceso de edición/revisión, permitiendo la previsualización del contenido antes de realizar el commit, analizando la sintaxis de Markdown y generando automáticamente el índice a medida que se crean/modifican los títulos de las secciones. 81 | 82 | * Markdown-lint: 83 | * Markdown-toc: 84 | * Markdown-all-in-one: 85 | * YAML: 86 | * Helm-intellisense: 87 | * GitLens: 88 | * Temas para VSCode: 89 | * 90 | * 91 | * 92 | -------------------------------------------------------------------------------- /es/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Resumen 2 | 3 | ## Acerca de 4 | 5 | * [Introducción](README.md) 6 | 7 | ## Capítulos 8 | 9 | * [Simplificando Kubernetes día 1](day-1/README.md) 10 | * [Simplificando Kubernetes día 2](day-2/README.md) 11 | * [Simplificando Kubernetes día 3](day-3/README.md) 12 | * [Simplificando Kubernetes día 4](day-4/README.md) 13 | * [Simplificando Kubernetes día 5](day-5/README.md) 14 | * [Simplificando Kubernetes día 6](day-6/README.md) 15 | * [Simplificando Kubernetes día 7](day-7/README.md) 16 | * [Simplificando Kubernetes día 8](day-8/README.md) 17 | * [Simplificando Kubernetes día 9](day-9/README.md) 18 | * [Simplificando Kubernetes día 10](day-10/README.md) 19 | * [Simplificando Kubernetes día 11](day-11/README.md) 20 | * [Simplificando Kubernetes día 12](day-12/README.md) 21 | * [Simplificando Kubernetes día 13](day-13/README.md) 22 | * [Simplificando Kubernetes día 14](day-14/README.md) 23 | * [Simplificando Kubernetes día 15](day-15/README.md) 24 | 25 | ## Contribuir 26 | 27 | * [Cómo ayudar](CONTRIBUTING.md) 28 | -------------------------------------------------------------------------------- /es/day-1/files/desafio/mi-primer-pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1beta1 2 | kind: pods 3 | metadata: 4 | labels: 5 | run: nginx-giropops 6 | app: giropops-strigus 7 | name: nginx_giropops 8 | spec: 9 | containers: 10 | - image: nginx 11 | name: nginx_giropops 12 | ports: 13 | - containerPort: 80 14 | resources: 15 | limits: 16 | memory: 17 | cpu: "0.5" 18 | requests: 19 | memory: "4400MB" 20 | cpu: "0,3" 21 | dnsPolicy: ClusterSecond 22 | restartPolicy: Always 23 | -------------------------------------------------------------------------------- /es/day-10/README.md: -------------------------------------------------------------------------------- 1 | # Simplificando Kubernetes 2 | 3 | ## DÍA 10 4 | 5 |   6 | 7 | ### ¿Qué veremos hoy? 8 | 9 | Durante el día de hoy, 10 | 11 |   12 | 13 | ### Contenido del Día 10 14 | 15 | - [¿Por qué?](#por-que-) 16 | 17 |   18 | 19 | ### ¿Por qué? 20 | 21 |   22 | 23 |   24 | 25 | ### Tu tarea 26 | 27 | Tu tarea es 28 | 29 |   30 | 31 | ## Desafío del Día 10 32 | 33 | No olvides 34 | 35 |   36 | 37 | ## Final del Día 10 38 | 39 | Durante el Día 10, has aprendido 40 | 41 |   42 | -------------------------------------------------------------------------------- /es/day-11/README.md: -------------------------------------------------------------------------------- 1 | # Simplificando Kubernetes 2 | 3 | ## Día 11 4 | 5 |   6 | 7 | ## Contenido del Día 11 8 | 9 | - [Simplificando Kubernetes](#simplificando-kubernetes) 10 | - [Día 11](#día-11) 11 | - [Contenido del Día 11](#contenido-del-día-11) 12 | - [Comienzo de la lección del Día 11](#comienzo-de-la-lección-del-día-11) 13 | - [¿Qué veremos hoy?](#qué-veremos-hoy) 14 | - [Introducción al Escalador Automático de Pods Horizontales (HPA)](#introducción-al-escalador-automático-de-pods-horizontales-hpa) 15 | - [¿Cómo funciona el HPA?](#cómo-funciona-el-hpa) 16 | - [Introducción al Metrics Server](#introducción-al-metrics-server) 17 | - [¿Por qué es importante el Metrics Server para el HPA?](#por-qué-es-importante-el-metrics-server-para-el-hpa) 18 | - [Instalación del Metrics Server](#instalación-del-metrics-server) 19 | - [En Amazon EKS y la mayoría de los clústeres Kubernetes](#en-amazon-eks-y-la-mayoría-de-los-clústeres-kubernetes) 20 | - [En Minikube](#en-minikube) 21 | - [En KinD (Kubernetes in Docker)](#en-kind-kubernetes-in-docker) 22 | - [Verificando la Instalación del Metrics Server](#verificando-la-instalación-del-metrics-server) 23 | - [Obteniendo Métricas](#obteniendo-métricas) 24 | - [Creando un HPA](#creando-un-hpa) 25 | - [Ejemplos Prácticos con HPA](#ejemplos-prácticos-con-hpa) 26 | - [Escalado automático basado en el uso de CPU](#escalado-automático-basado-en-el-uso-de-cpu) 27 | - [Escalado automático basado en el uso de Memoria](#escalado-automático-basado-en-el-uso-de-memoria) 28 | - [Configuración Avanzada de HPA: Definición del Comportamiento de Escalado](#configuración-avanzada-de-hpa-definición-del-comportamiento-de-escalado) 29 | - [ContainerResource](#containerresource) 30 | - [Detalles del Algoritmo de Escalado](#detalles-del-algoritmo-de-escalado) 31 | - [Configuraciones Avanzadas y Uso Práctico](#configuraciones-avanzadas-y-uso-práctico) 32 | - [Integración del HPA con Prometheus para Métricas Personalizadas](#integración-del-hpa-con-prometheus-para-métricas-personalizadas) 33 | - [Tu Tarea](#tu-tarea) 34 | - [Fin del Día 11](#fin-del-día-11) 35 | 36 |   37 | 38 | ### Comienzo de la lección del Día 11 39 | 40 | #### ¿Qué veremos hoy? 41 | 42 | ¡Hoy es un día particularmente fascinante! Vamos a explorar los territorios de Kubernetes, adentrándonos en la magia del Escalador Automático de Pods Horizontales (Horizontal Pod Autoscaler - HPA, por sus siglas en inglés), una herramienta indispensable para aquellos que buscan una operación eficiente y resistente. Así que abróchense los cinturones y prepárense para un viaje de descubrimientos. ¡La aventura #VAIIII comienza! 43 | 44 | #### Introducción al Escalador Automático de Pods Horizontales (HPA) 45 | 46 | El Escalador Automático de Pods Horizontales, cariñosamente conocido como HPA, es una de las joyas brillantes incrustadas en el corazón de Kubernetes. Con el HPA, podemos ajustar automáticamente el número de réplicas de un conjunto de pods, asegurando que nuestra aplicación siempre tenga los recursos necesarios para funcionar de manera eficiente, sin desperdiciar recursos. El HPA es como un director de orquesta que, con la batuta de las métricas, dirige la orquesta de pods, asegurando que la armonía se mantenga incluso cuando la sinfonía del tráfico de red alcance su clímax. 47 | 48 | #### ¿Cómo funciona el HPA? 49 | 50 | El HPA es el vigilante que monitorea las métricas de nuestros pods. En cada latido de su corazón métrico, que ocurre a intervalos regulares, evalúa si los pods están esforzándose al máximo para satisfacer las demandas o si están descansando más de lo necesario. Basándose en esta evaluación, toma la sabia decisión de convocar a más soldados al campo de batalla o de darles un merecido descanso. 51 | 52 | ¿El servidor de métricas es importante para el funcionamiento del Escalador Automático de Pods Horizontales (HPA)? ¡Absolutamente! El servidor de métricas es un componente crucial, ya que proporciona las métricas necesarias para que el HPA tome decisiones de escalado. Ahora, profundicemos un poco más en el servidor de métricas y cómo instalarlo en diferentes entornos de Kubernetes, incluyendo Minikube y KinD. 53 | 54 | ## Introducción al Metrics Server 55 | 56 | Antes de comenzar a explorar el Escalador Automático de Pods Horizontales (HPA), es esencial tener el Metrics Server instalado en nuestro clúster Kubernetes. El Metrics Server es un agregador de métricas de recursos del sistema que recopila métricas como el uso de la CPU y la memoria de los nodos y pods en el clúster. Estas métricas son vitales para el funcionamiento del HPA, ya que se utilizan para determinar cuándo y cómo escalar los recursos. 57 | 58 | ### ¿Por qué es importante el Metrics Server para el HPA? 59 | 60 | El HPA utiliza métricas de uso de recursos para tomar decisiones inteligentes sobre la escalabilidad de los pods. Por ejemplo, si el uso de la CPU de un pod supera cierto límite, el HPA puede decidir aumentar el número de réplicas de ese pod. Del mismo modo, si el uso de la CPU es muy bajo, el HPA puede decidir reducir el número de réplicas. Para hacer esto de manera efectiva, el HPA necesita acceder a métricas precisas y actualizadas, que son proporcionadas por el Metrics Server. 61 | Por lo tanto, es fundamental comprender esta pieza clave para el día de hoy. :D 62 | 63 | ### Instalación del Metrics Server 64 | 65 | #### En Amazon EKS y la mayoría de los clústeres Kubernetes 66 | 67 | Durante nuestra lección, estoy utilizando un clúster EKS, y para instalar el Metrics Server, podemos utilizar el siguiente comando: 68 | 69 | ```bash 70 | kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml 71 | ``` 72 | 73 | Este comando aplica el manifiesto del Metrics Server a su clúster, instalando todos los componentes necesarios. 74 | 75 | #### En Minikube 76 | 77 | La instalación del Metrics Server en Minikube es bastante sencilla. Utilice el siguiente comando para habilitar el Metrics Server: 78 | 79 | ```bash 80 | minikube addons enable metrics-server 81 | ``` 82 | 83 | Después de ejecutar este comando, el Metrics Server se instalará y activará en su clúster Minikube. 84 | 85 | #### En KinD (Kubernetes in Docker) 86 | 87 | Para KinD, puede utilizar el mismo comando que utilizó para EKS: 88 | 89 | ```bash 90 | kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml 91 | ``` 92 | 93 | #### Verificando la Instalación del Metrics Server 94 | 95 | Después de instalar el Metrics Server, es una buena práctica verificar si se ha instalado correctamente y si está funcionando según lo previsto. Ejecute el siguiente comando para obtener la lista de pods en el espacio de nombres `kube-system` y verificar si el pod del Metrics Server está en ejecución: 96 | 97 | ```bash 98 | kubectl get pods -n kube-system | grep metrics-server 99 | ``` 100 | 101 | #### Obteniendo Métricas 102 | 103 | Con el Metrics Server en funcionamiento, ahora puede comenzar a recopilar métricas de su clúster. Aquí hay un ejemplo de cómo puede obtener métricas de uso de CPU y memoria para todos sus nodos: 104 | 105 | ```bash 106 | kubectl top nodes 107 | ``` 108 | 109 | Y para obtener métricas de uso de CPU y memoria para todos sus pods: 110 | 111 | ```bash 112 | kubectl top pods 113 | ``` 114 | 115 | Estos comandos proporcionan una visión rápida del uso de recursos en su clúster, lo cual es fundamental para comprender y optimizar el rendimiento de sus aplicaciones. 116 | 117 | ### Creando un HPA 118 | 119 | Antes de profundizar en el HPA, hagamos un resumen creando un despliegue simple para nuestro confiable servidor Nginx. 120 | 121 | ```yaml 122 | # Definición de un Despliegue para el servidor Nginx 123 | apiVersion: apps/v1 # Versión de la API que define un Despliegue 124 | kind: Deployment # Tipo de recurso que estamos definiendo 125 | metadata: 126 | name: nginx-deployment # Nombre de nuestro Despliegue 127 | spec: 128 | replicas: 3 # Número inicial de réplicas 129 | selector: 130 | matchLabels: 131 | app: nginx # Etiqueta que identifica los pods de este Despliegue 132 | template: 133 | metadata: 134 | labels: 135 | app: nginx # Etiqueta aplicada a los pods 136 | spec: 137 | containers: 138 | - name: nginx # Nombre del contenedor 139 | image: nginx:latest # Imagen del contenedor 140 | ports: 141 | - containerPort: 80 # Puerto expuesto por el contenedor 142 | resources: 143 | limits: 144 | cpu: 500m # Límite de CPU 145 | memory: 256Mi # Límite de memoria 146 | requests: 147 | cpu: 250m # Solicitud de CPU 148 | memory: 128Mi # Solicitud de memoria 149 | ``` 150 | 151 | Ahora, con nuestro despliegue listo, demos el siguiente paso en la creación de nuestro HPA. 152 | 153 | ```yaml 154 | # Definición del HPA para nginx-deployment 155 | apiVersion: autoscaling/v2 # Versión de la API que define un HPA 156 | kind: HorizontalPodAutoscaler # Tipo de recurso que estamos definiendo 157 | metadata: 158 | name: nginx-deployment-hpa # Nombre de nuestro HPA 159 | spec: 160 | scaleTargetRef: 161 | apiVersion: apps/v1 # Versión de la API del recurso objetivo 162 | kind: Deployment # Tipo de recurso objetivo 163 | name: nginx-deployment # Nombre del recurso objetivo 164 | minReplicas: 3 # Número mínimo de réplicas 165 | maxReplicas: 10 # Número máximo de réplicas 166 | metrics: 167 | - type: Resource # Tipo de métrica (recurso del sistema) 168 | resource: 169 | name: cpu # Nombre de la métrica (CPU en este caso) 170 | target: 171 | type: Utilization # Tipo de destino (utilización) 172 | averageUtilization: 50 # Valor objetivo (50% de utilización) 173 | ``` 174 | 175 | En este ejemplo, creamos un HPA que supervisa el uso de la CPU de nuestro `nginx-deployment`. El HPA se esforzará por mantener el uso de la CPU en torno al 50%, ajustando el número de réplicas entre 3 y 10 según sea necesario. 176 | 177 | Para aplicar esta configuración a su clúster Kubernetes, guarde el contenido anterior en un archivo llamado `nginx-deployment-hpa.yaml` y ejecute el siguiente comando: 178 | 179 | ```bash 180 | kubectl apply -f nginx-deployment-hpa.yaml 181 | ``` 182 | 183 | Ahora que tienes un HPA supervisando y ajustando la escala de tu `nginx-deployment` basado en el uso de la CPU. ¡Fantástico, ¿verdad? 184 | 185 | ### Ejemplos Prácticos con HPA 186 | 187 | Ahora que ya tienes una comprensión básica del HPA, es hora de poner manos a la obra. Exploraremos cómo el HPA responde a diferentes métricas y escenarios. 188 | 189 | #### Escalado automático basado en el uso de CPU 190 | 191 | Comencemos con un ejemplo clásico de escalado basado en el uso de la CPU, que ya discutimos anteriormente. Para que el aprendizaje sea más interactivo, simularemos un aumento de tráfico y observaremos cómo el HPA responde a este cambio. 192 | 193 | ```bash 194 | kubectl run -i --tty load-generator --image=busybox /bin/sh 195 | 196 | while true; do wget -q -O- http://nginx-deployment.default.svc.cluster.local; done 197 | ``` 198 | 199 | Este sencillo script crea una carga constante en nuestro despliegue, realizando solicitudes continuas al servidor Nginx. Podrás observar cómo el HPA ajusta el número de réplicas para mantener el uso de la CPU cerca del límite definido. 200 | 201 | #### Escalado automático basado en el uso de Memoria 202 | 203 | El HPA no solo es experto en el manejo de la CPU, sino que también tiene un agudo sentido para la memoria. Exploraremos cómo configurar el HPA para escalar basado en el uso de la memoria. 204 | 205 | ```yaml 206 | # Definición del HPA para escalado basado en memoria 207 | apiVersion: autoscaling/v2 # Versión de la API que define un HPA 208 | kind: HorizontalPodAutoscaler # Tipo de recurso que estamos definiendo 209 | metadata: 210 | name: nginx-deployment-hpa-memory # Nombre de nuestro HPA 211 | spec: 212 | scaleTargetRef: 213 | apiVersion: apps/v1 # Versión de la API del recurso objetivo 214 | kind: Deployment # Tipo de recurso objetivo 215 | name: nginx-deployment # Nombre del recurso objetivo 216 | minReplicas: 3 # Número mínimo de réplicas 217 | maxReplicas: 10 # Número máximo de réplicas 218 | metrics: 219 | - type: Resource # Tipo de métrica (recurso del sistema) 220 | resource: 221 | name: memory # Nombre de la métrica (memoria en este caso) 222 | target: 223 | type: Utilization # Tipo de objetivo (utilización) 224 | averageUtilization: 70 # Valor objetivo (70% de utilización) 225 | ``` 226 | 227 | En este ejemplo, el HPA ajustará el número de réplicas para mantener el uso de la memoria en alrededor del 70%. De esta manera, nuestro despliegue puede funcionar sin problemas incluso cuando la demanda aumenta. 228 | 229 | #### Configuración Avanzada de HPA: Definición del Comportamiento de Escalado 230 | 231 | El HPA es flexible y te permite definir cómo debe comportarse durante el escalado hacia arriba y hacia abajo. Vamos a explorar un ejemplo: 232 | 233 | ```yaml 234 | # Definición de HPA con configuración avanzada de comportamiento 235 | apiVersion: autoscaling/v2 # Versión de la API que define un HPA 236 | kind: HorizontalPodAutoscaler # Tipo de recurso que estamos definiendo 237 | metadata: 238 | name: nginx-deployment-hpa # Nombre de nuestro HPA 239 | spec: 240 | scaleTargetRef: 241 | apiVersion: apps/v1 # Versión de la API del recurso objetivo 242 | kind: Deployment # Tipo de recurso objetivo 243 | name: nginx-deployment # Nombre del recurso objetivo 244 | minReplicas: 3 # Número mínimo de réplicas 245 | maxReplicas: 10 # Número máximo de réplicas 246 | metrics: 247 | - type: Resource # Tipo de métrica (recurso del sistema) 248 | resource: 249 | name: cpu # Nombre de la métrica (CPU en este caso) 250 | target: 251 | type: Utilization # Tipo de objetivo (utilización) 252 | averageUtilization: 50 # Valor objetivo (50% de utilización) 253 | behavior: 254 | scaleUp: 255 | stabilizationWindowSeconds: 0 # Período de estabilización para el escalado hacia arriba 256 | policies: 257 | - type: Percent # Tipo de política (porcentaje) 258 | value: 100 # Valor de la política (100%) 259 | periodSeconds: 15 # Período de la política (15 segundos) 260 | scaleDown: 261 | stabilizationWindowSeconds: 300 # Período de estabilización para el escalado hacia abajo 262 | policies: 263 | - type: Percent # Tipo de política (porcentaje) 264 | value: 100 # Valor de la política (100%) 265 | periodSeconds: 15 # Período de la política (15 segundos) 266 | ``` 267 | 268 | En este ejemplo, especificamos un comportamiento de escalado en el que el HPA puede escalar hacia arriba de inmediato, pero esperará durante 5 minutos (300 segundos) después del último escalado hacia arriba antes de considerar un escalado hacia abajo. Esto ayuda a evitar fluctuaciones rápidas en el recuento de réplicas, proporcionando un entorno más estable para nuestros pods. 269 | 270 | #### ContainerResource 271 | 272 | El tipo de métrica `ContainerResource` en Kubernetes te permite especificar métricas de recursos específicas del contenedor para el escalado. A diferencia de las métricas de recursos comunes que se aplican a todos los contenedores en un Pod, las métricas `ContainerResource` te permiten especificar métricas para un contenedor específico dentro de un Pod. Esto puede ser útil en escenarios en los que tienes múltiples contenedores en un Pod, pero deseas escalar en función del uso de recursos de un contenedor en particular. 273 | 274 | Aquí tienes un ejemplo de cómo configurar un Horizontal Pod Autoscaler (HPA) utilizando una métrica `ContainerResource` para escalar un Deployment en función del uso de CPU de un contenedor específico: 275 | 276 | ```yaml 277 | apiVersion: autoscaling/v2beta2 278 | kind: HorizontalPodAutoscaler 279 | metadata: 280 | name: nginx-hpa 281 | spec: 282 | scaleTargetRef: 283 | apiVersion: apps/v1 284 | kind: Deployment 285 | name: nginx 286 | minReplicas: 3 287 | maxReplicas: 10 288 | metrics: 289 | - type: ContainerResource 290 | containerResource: 291 | name: cpu 292 | container: nginx-NOMBRE-COMPLETO-DEL-CONTENEDOR 293 | target: 294 | type: Utilization 295 | averageUtilization: 50 296 | ``` 297 | 298 | En el ejemplo anterior: 299 | 300 | - El tipo de métrica se define como `ContainerResource`. 301 | - Dentro del bloque `containerResource`, especificamos el nombre de la métrica (`cpu`), el nombre del contenedor (`mi-contenedor`) y el objetivo de utilización (`averageUtilization: 50`). 302 | 303 | Esto significa que el HPA ajustará el número de réplicas del Deployment `my-app` para mantener el uso promedio de CPU del contenedor `nginx-NOMBRE-COMPLETO-DEL-CONTENEDOR` en alrededor del 50%. 304 | 305 | Este tipo de configuración permite un control más granular sobre el comportamiento del escalado automático, especialmente en entornos donde los Pods contienen múltiples contenedores con perfiles de uso de recursos diferentes. 306 | 307 | #### Detalles del Algoritmo de Escalado 308 | 309 | **Cálculo del Número de Réplicas** 310 | El núcleo del Horizontal Pod Autoscaler (HPA) es su algoritmo de escalado, que determina el número óptimo de réplicas en función de las métricas proporcionadas. La fórmula básica utilizada por el HPA para calcular el número deseado de réplicas es: 311 | 312 | \[ \text{desiredReplicas} = \lceil \text{currentReplicas} \times \left( \frac{\text{currentMetricValue}}{\text{desiredMetricValue}} \right) \rceil \] 313 | 314 | **Ejemplos con Valores Específicos:** 315 | 316 | 1. **Ejemplo de Escalado hacia Arriba:** 317 | - Réplicas actuales: 2 318 | - Valor actual de la métrica (CPU): 80% 319 | - Valor deseado de la métrica (CPU): 50% 320 | - Cálculo: \(\lceil 2 \times (80\% / 50\%) \rceil = \lceil 3.2 \rceil = 4\) réplicas 321 | 322 | 2. **Ejemplo de Escalado hacia Abajo:** 323 | - Réplicas actuales: 5 324 | - Valor actual de la métrica (CPU): 30% 325 | - Valor deseado de la métrica (CPU): 50% 326 | - Cálculo: \(\lceil 5 \times (30\% / 50\%) \rceil = \lceil 3 \rceil = 3\) réplicas 327 | 328 | **Consideraciones sobre Métricas y Estado de los Pods:** 329 | 330 | - **Métricas de Recursos por Pod y Personalizadas:** El HPA se puede configurar para utilizar métricas estándar (como CPU y memoria) o métricas personalizadas definidas por el usuario, lo que permite una mayor flexibilidad. 331 | - **Tratamiento de Pods sin Métricas o no Listos:** Si un Pod no tiene métricas disponibles o no está listo, puede ser excluido del cálculo promedio, evitando decisiones de escalado basadas en datos incompletos. 332 | 333 | #### Configuraciones Avanzadas y Uso Práctico 334 | 335 | **Configuración de Métricas Personalizadas y Múltiples Métricas:** 336 | El HPA no se limita a métricas de CPU y memoria; se puede configurar para utilizar una variedad de métricas personalizadas. 337 | 338 | **Uso de Métricas Personalizadas: Ejemplos y Consejos:** 339 | 340 | - **Ejemplo:** Supongamos que tiene un servicio que debe escalar según el número de solicitudes HTTP por segundo. Puede configurar el HPA para escalar en función de esta métrica personalizada. 341 | - **Consejos:** Al utilizar métricas personalizadas, asegúrese de que las métricas sean un indicador confiable de la carga de trabajo y de que el servicio de métricas esté configurado correctamente y sea accesible para el HPA. 342 | 343 | **Escalado Basado en Múltiples Métricas:** 344 | 345 | - El HPA se puede configurar para tener en cuenta varias métricas al mismo tiempo, lo que permite un control más refinado del escalado. 346 | - Por ejemplo, puede configurar el HPA para escalar en función tanto del uso de la CPU como de la memoria, o cualquier combinación de métricas estándar y personalizadas. 347 | 348 | #### Integración del HPA con Prometheus para Métricas Personalizadas 349 | 350 | Para llevar el escalado automático al siguiente nivel, podemos integrar el HPA con Prometheus. Con esta integración, podemos utilizar métricas de Prometheus para informar nuestras decisiones de escalado automático. 351 | 352 | La integración generalmente implica configurar un adaptador de métricas personalizadas, como el `k8s-prometheus-adapter`. Una vez configurado, el HPA puede acceder a las métricas de Prometheus y utilizarlas para tomar decisiones de escalado automático. Puede encontrar la documentación completa sobre cómo integrar el HPA con Prometheus [aquí](#enlace-a-la-documentación). 353 | 354 | ### Tu Tarea 355 | 356 | Ahora que has adquirido conocimientos sobre el HPA, es hora de poner en práctica ese conocimiento. Configura un HPA en tu entorno y experimenta con diferentes métricas: CPU, memoria y métricas personalizadas. Documenta tus observaciones y comprende cómo responde el HPA a diferentes cargas y situaciones. 357 | 358 | ### Fin del Día 11 359 | 360 | Y así llegamos al final del Día 11, un viaje lleno de aprendizaje y exploración. Hoy has descubierto el poder del Horizontal Pod Autoscaler y cómo puede ayudar a que tu aplicación funcione eficientemente incluso bajo diferentes condiciones de carga. No solo has aprendido cómo funciona, sino que también has puesto en práctica ejemplos prácticos. Sigue practicando y explorando, ¡y nos vemos en el próximo día de nuestra aventura en Kubernetes! #VAIIII 361 | -------------------------------------------------------------------------------- /es/day-12/README.md: -------------------------------------------------------------------------------- 1 | # Simplificando Kubernetes 2 | 3 | ## Día 12: Dominando Taints y Tolerations 4 | 5 |   6 | 7 | ## Contenido del Día 12 8 | 9 | - [Simplificando Kubernetes](#simplificando-kubernetes) 10 | - [Día 12: Dominando Taints y Tolerations](#día-12-dominando-taints-y-tolerations) 11 | - [Contenido del Día 12](#contenido-del-día-12) 12 | - [Introducción](#introducción) 13 | - [¿Qué son Taints y Tolerations?](#qué-son-taints-y-tolerations) 14 | - [¿Por qué usar Taints y Tolerations?](#por-qué-usar-taints-y-tolerations) 15 | - [Anatomía de un Taint](#anatomía-de-un-taint) 16 | - [Anatomía de una Tolerations](#anatomía-de-una-tolerations) 17 | - [Aplicación de Taints](#aplicación-de-taints) 18 | - [Configuración de Tolerations](#configuración-de-tolerations) 19 | - [Escenarios de Uso](#escenarios-de-uso) 20 | - [Aislamiento de Cargas de Trabajo](#aislamiento-de-cargas-de-trabajo) 21 | - [Nodos Especializados](#nodos-especializados) 22 | - [Toleration en un Pod que Requiere GPU:](#toleration-en-un-pod-que-requiere-gpu) 23 | - [Evacuación y Mantenimiento de Nodos](#evacuación-y-mantenimiento-de-nodos) 24 | - [Combinando Taints y Tolerations con Reglas de Afinidad](#combinando-taints-y-tolerations-con-reglas-de-afinidad) 25 | - [Ejemplos Prácticos](#ejemplos-prácticos) 26 | - [Ejemplo 1: Aislamiento de Cargas de Trabajo](#ejemplo-1-aislamiento-de-cargas-de-trabajo) 27 | - [Ejemplo 2: Utilización de Hardware Especializado](#ejemplo-2-utilización-de-hardware-especializado) 28 | - [Ejemplo 3: Mantenimiento de Nodos](#ejemplo-3-mantenimiento-de-nodos) 29 | - [Conclusión](#conclusión) 30 | - [Tareas del Día](#tareas-del-día) 31 | - [DÍA 12+1: Comprendiendo y Dominando los Selectores](#día-121-comprendiendo-y-dominando-los-selectores) 32 | - [Introducción 12+1](#introducción-121) 33 | - [¿Qué son los Selectors?](#qué-son-los-selectors) 34 | - [Tipos de Selectors](#tipos-de-selectors) 35 | - [Equality-based Selectors](#equality-based-selectors) 36 | - [Set-based Selectors](#set-based-selectors) 37 | - [Selectors en acción](#selectors-en-acción) 38 | - [En Services](#en-services) 39 | - [En ReplicaSets](#en-replicasets) 40 | - [En Jobs y CronJobs](#en-jobs-y-cronjobs) 41 | - [Selectores y Namespaces](#selectores-y-namespaces) 42 | - [Escenarios de uso](#escenarios-de-uso-1) 43 | - [Enrutamiento de tráfico](#enrutamiento-de-tráfico) 44 | - [Escalado horizontal](#escalado-horizontal) 45 | - [Desastre y recuperación](#desastre-y-recuperación) 46 | - [Consejos y trampas](#consejos-y-trampas) 47 | - [Ejemplos prácticos](#ejemplos-prácticos-1) 48 | - [Ejemplo 1: Selector en un Service](#ejemplo-1-selector-en-un-service) 49 | - [Ejemplo 2: Selector en un ReplicaSet](#ejemplo-2-selector-en-un-replicaset) 50 | - [Ejemplo 3: Selectors avanzados](#ejemplo-3-selectors-avanzados) 51 | - [Conclusión 12+1](#conclusión-121) 52 | 53 | ### Introducción 54 | 55 | ¡Hola a todos! En el capítulo de hoy, vamos a sumergirnos profundamente en uno de los conceptos más poderosos y flexibles de Kubernetes: Taints (Marcas) y Tolerations (Tolerancias). Prepárense, porque este capítulo va más allá de lo básico y entra en detalles que no querrán perderse. #VAMOS 56 | 57 | ### ¿Qué son Taints y Tolerations? 58 | 59 | Los Taints son "manchas" o "marcas" aplicadas a los Nodos que los marcan para evitar que ciertos Pods sean programados en ellos. Por otro lado, las Tolerations son configuraciones que se pueden aplicar a los Pods para permitir que sean programados en Nodos con Taints específicos. 60 | 61 | ### ¿Por qué usar Taints y Tolerations? 62 | 63 | En un clúster Kubernetes diverso, no todos los Nodos son iguales. Algunos pueden tener acceso a recursos especiales como GPUs, mientras que otros pueden estar reservados para cargas de trabajo críticas. Los Taints y Tolerations proporcionan un mecanismo para asegurar que los Pods se programen en los Nodos adecuados. 64 | 65 | ### Anatomía de un Taint 66 | 67 | Un Taint está compuesto por una `clave`, un `valor` y un `efecto`. El efecto puede ser: 68 | 69 | - `NoSchedule`: Kubernetes no programa el Pod a menos que tenga una Tolerations correspondiente. 70 | - `PreferNoSchedule`: Kubernetes intenta no programar, pero no hay garantía. 71 | - `NoExecute`: Los Pods existentes son eliminados si no tienen una Tolerations correspondiente. 72 | 73 | ### Anatomía de una Tolerations 74 | 75 | Una Tolerations se define mediante los mismos elementos que un Taint: `clave`, `valor` y `efecto`. Además, contiene un `operador`, que puede ser `Equal` o `Exists`. 76 | 77 | ### Aplicación de Taints 78 | 79 | Para aplicar un Taint a un Nodo, puedes utilizar el comando `kubectl taint`. Por ejemplo: 80 | 81 | ```bash 82 | kubectl taint nodes nodo1 clave=valor:NoSchedule 83 | ``` 84 | 85 | ### Configuración de Tolerations 86 | 87 | Las Tolerations se configuran en el PodSpec. Aquí tienes un ejemplo: 88 | 89 | ```yaml 90 | apiVersion: v1 91 | kind: Pod 92 | metadata: 93 | name: my-pod 94 | spec: 95 | tolerations: 96 | - key: "key" 97 | operator: "Equal" 98 | value: "value" 99 | effect: "NoSchedule" 100 | ``` 101 | 102 | ### Escenarios de Uso 103 | 104 | #### Aislamiento de Cargas de Trabajo 105 | 106 | Imagina un escenario en el que tienes Nodos que deben estar dedicados a cargas de trabajo de producción y no deben ejecutar Pods de desarrollo. 107 | 108 | Aplicación de Taint: 109 | 110 | ```bash 111 | kubectl taint nodes prod-node environment=production:NoSchedule 112 | ``` 113 | 114 | Tolerancia en el Pod de producción: 115 | 116 | ```yaml 117 | tolerations: 118 | - key: "environment" 119 | operator: "Equal" 120 | value: "producción" 121 | effect: "NoSchedule" 122 | ``` 123 | 124 | #### Nodos Especializados 125 | 126 | Si tienes Nodos con GPUs y deseas asegurarte de que solo se programen Pods que necesiten GPUs allí. 127 | 128 | Aplicación de Taint: 129 | 130 | ```bash 131 | kubectl taint nodes gpu-node gpu=true:NoSchedule 132 | ``` 133 | 134 | #### Toleration en un Pod que Requiere GPU: 135 | 136 | ```yaml 137 | tolerations: 138 | - key: "gpu" 139 | operator: "Equal" 140 | value: "true" 141 | effect: "NoSchedule" 142 | ``` 143 | 144 | #### Evacuación y Mantenimiento de Nodos 145 | 146 | Si necesitas realizar mantenimiento en un Nodo y deseas evitar que se programen nuevos Pods en él. 147 | 148 | Aplicar Taint: 149 | 150 | ```bash 151 | kubectl taint nodes node1 maintenance=true:NoExecute 152 | ``` 153 | 154 | #### Combinando Taints y Tolerations con Reglas de Afinidad 155 | 156 | Puedes combinar Taints y Tolerations con reglas de afinidad para un control aún más granular. 157 | 158 | ### Ejemplos Prácticos 159 | 160 | #### Ejemplo 1: Aislamiento de Cargas de Trabajo 161 | 162 | Creemos un Nodo con un Taint y tratemos de programar un Pod sin la Toleration correspondiente. 163 | 164 | ```bash 165 | # Aplicar Taint 166 | kubectl taint nodes dev-node environment=development:NoSchedule 167 | 168 | # Intentar programar el Pod 169 | kubectl run nginx --image=nginx 170 | ``` 171 | 172 | Observa que el Pod no se programará hasta que se agregue una Toleration correspondiente. 173 | 174 | #### Ejemplo 2: Utilización de Hardware Especializado 175 | 176 | Creemos un Nodo con una GPU y apliquemos un Taint correspondiente. 177 | 178 | ```bash 179 | # Aplicar Taint 180 | kubectl taint nodes gpu-node gpu=true:NoSchedule 181 | 182 | # Programar Pod con Toleration 183 | kubectl apply -f gpu-pod.yaml 184 | ``` 185 | 186 | Donde `gpu-pod.yaml` contiene la Toleration correspondiente. 187 | 188 | #### Ejemplo 3: Mantenimiento de Nodos 189 | 190 | Simulemos un mantenimiento aplicando un Taint a un Nodo y observemos cómo se eliminan los Pods. 191 | 192 | ```bash 193 | # Aplicar Taint 194 | kubectl taint nodes node1 maintenance=true:NoExecute 195 | ``` 196 | 197 | Estos ejemplos prácticos te ayudarán a comprender mejor cómo funcionan los Taints y Tolerations en situaciones del mundo real. 198 | 199 | ### Conclusión 200 | 201 | Taints y Tolerations son herramientas poderosas para un control refinado de la programación de Pods. Con ellas, puedes aislar workloads, aprovechar hardware especializado e incluso gestionar el mantenimiento de manera más eficaz. 202 | 203 | ### Tareas del Día 204 | 205 | 1. Aplica un Taint en uno de tus Nodos y trata de programar un Pod sin la Toleration correspondiente. 206 | 2. Elimina el Taint y observa el comportamiento. 207 | 3. Agrega una Toleration al Pod y repite el proceso. 208 | 209 | ## DÍA 12+1: Comprendiendo y Dominando los Selectores 210 | 211 | ### Introducción 12+1 212 | 213 | ¡Hola a todos! En el capítulo de hoy, profundizaremos en uno de los recursos más versátiles y fundamentales de Kubernetes: los Selectores. ¿Están listos? ¡Entonces #VAMOS! 214 | 215 | ### ¿Qué son los Selectors? 216 | 217 | Los Selectors son formas de seleccionar recursos, como Pods, en función de sus etiquetas. Son el pegamento que une varios componentes de Kubernetes, como Services y RéplicaSets. 218 | 219 | ### Tipos de Selectors 220 | 221 | #### Equality-based Selectors 222 | 223 | Estos son los más simples y utilizan operadores como `=`, `==` y `!=`. 224 | 225 | Ejemplo: 226 | 227 | ```bash 228 | kubectl get pods -l environment=production 229 | ``` 230 | 231 | #### Set-based Selectors 232 | 233 | Estos son más complejos y utilizan operadores como `in`, `notin` y `exists`. 234 | 235 | Ejemplo: 236 | 237 | ```bash 238 | kubectl get pods -l 'environment in (production, qa)' 239 | ``` 240 | 241 | ### Selectors en acción 242 | 243 | #### En Services 244 | 245 | Los Services utilizan selectores para dirigir el tráfico hacia Pods específicos. 246 | 247 | Ejemplo: 248 | 249 | ```yaml 250 | apiVersion: v1 251 | kind: Service 252 | metadata: 253 | name: my-service 254 | spec: 255 | selector: 256 | app: MyApp 257 | ``` 258 | 259 | #### En ReplicaSets 260 | 261 | Los ReplicaSets utilizan selectores para saber qué Pods gestionar. 262 | 263 | Ejemplo: 264 | 265 | ```yaml 266 | apiVersion: apps/v1 267 | kind: ReplicaSet 268 | metadata: 269 | name: my-replicaset 270 | spec: 271 | selector: 272 | matchLabels: 273 | app: MyApp 274 | ``` 275 | 276 | #### En Jobs y CronJobs 277 | 278 | Los Jobs y CronJobs también pueden utilizar selectores para ejecutar tareas en Pods específicos. 279 | 280 | ### Selectores y Namespaces 281 | 282 | Es crucial entender que los selectores no atraviesan namespaces; son efectivos solo dentro del namespace actual a menos que se especifique de otra manera. 283 | 284 | ### Escenarios de uso 285 | 286 | #### Enrutamiento de tráfico 287 | 288 | Utilice Selectors en los Services para dirigir el tráfico hacia versiones específicas de una aplicación. 289 | 290 | #### Escalado horizontal 291 | 292 | Utilice selectores en Horizontal Pod Autoscalers para escalar solo los Pods que cumplan con criterios específicos. 293 | 294 | #### Desastre y recuperación 295 | 296 | En casos de conmutación por error, puede utilizar selectores para dirigir el tráfico hacia Pods en un clúster secundario. 297 | 298 | ### Consejos y trampas 299 | 300 | - No cambie las etiquetas de los Pods que son objetivos de Services sin actualizar el selector del Service. 301 | - Utilice selectores de manera consistente para evitar confusiones. 302 | 303 | ### Ejemplos prácticos 304 | 305 | #### Ejemplo 1: Selector en un Service 306 | 307 | Vamos a crear un Service que seleccione todos los Pods con la etiqueta `frontend`. 308 | 309 | ```bash 310 | kubectl apply -f frontend-service.yaml 311 | ``` 312 | 313 | #### Ejemplo 2: Selector en un ReplicaSet 314 | 315 | Vamos a crear un ReplicaSet que gestione todos los Pods con la etiqueta `backend`. 316 | 317 | ```bash 318 | kubectl apply -f backend-replicaset.yaml 319 | ``` 320 | 321 | #### Ejemplo 3: Selectors avanzados 322 | 323 | Vamos a realizar una consulta compleja para seleccionar Pods basados en múltiples etiquetas. 324 | 325 | ```bash 326 | kubectl get pods -l 'release-version in (v1, v2),environment!=debug' 327 | ``` 328 | 329 | ### Conclusión 12+1 330 | 331 | Los selectores son una herramienta poderosa y flexible en Kubernetes, que permite un control preciso sobre cómo interactúan los recursos. Dominar este concepto es fundamental para cualquiera que trabaje con Kubernetes. 332 | -------------------------------------------------------------------------------- /es/day-14/images/image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/es/day-14/images/image-1.png -------------------------------------------------------------------------------- /es/day-14/images/image-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/es/day-14/images/image-2.png -------------------------------------------------------------------------------- /es/day-14/images/image-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/es/day-14/images/image-3.png -------------------------------------------------------------------------------- /es/day-4/files/nginx-deployment.yaml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /es/day-4/files/nginx-liveness.yaml: -------------------------------------------------------------------------------- 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 é onde vamos adicionar a nossa livenessProbe 29 | httpGet: # Aqui vamos utilizar o httpGet, onde vamos se conectar ao container através do protocolo HTTP 30 | path: /giropops # Qual o endpoint que vamos utilizar para se conectar ao container 31 | port: 80 # Qual porta TCP vamos utilizar para se conectar ao container 32 | initialDelaySeconds: 10 # Quantos segundos vamos esperar para executar a primeira verificação 33 | periodSeconds: 10 # A cada quantos segundos vamos executar a verificação 34 | timeoutSeconds: 5 # Quantos segundos vamos esperar para considerar que a verificação falhou 35 | failureThreshold: 3 # Quantos falhas consecutivas vamos aceitar antes de reiniciar o container 36 | -------------------------------------------------------------------------------- /es/day-4/files/nginx-readiness.yaml: -------------------------------------------------------------------------------- 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: # Onde definimos a nossa probe de leitura 29 | httpGet: # O tipo de teste que iremos executar, neste caso, iremos executar um teste HTTP 30 | path: /giropops # O caminho que iremos testar 31 | port: 80 # A porta que iremos testar 32 | initialDelaySeconds: 10 # O tempo que iremos esperar para executar a primeira vez a probe 33 | periodSeconds: 10 # De quanto em quanto tempo iremos executar a probe 34 | timeoutSeconds: 5 # O tempo que iremos esperar para considerar que a probe falhou 35 | successThreshold: 2 # O número de vezes que a probe precisa passar para considerar que o container está pronto 36 | failureThreshold: 3 # O número de vezes que a probe precisa falhar para considerar que o container não está pronto 37 | -------------------------------------------------------------------------------- /es/day-4/files/nginx-replicaset.yaml: -------------------------------------------------------------------------------- 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.3 19 | name: nginx 20 | resources: 21 | limits: 22 | cpu: "0.5" 23 | memory: 256Mi 24 | requests: 25 | cpu: 0.25 26 | memory: 128Mi 27 | -------------------------------------------------------------------------------- /es/day-4/files/nginx-startup.yaml: -------------------------------------------------------------------------------- 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: # Onde definimos a nossa probe de inicialização 29 | httpGet: # O tipo de teste que iremos executar, neste caso, iremos executar um teste HTTP 30 | path: / # O caminho que iremos testar 31 | port: 80 # A porta que iremos testar 32 | initialDelaySeconds: 10 # O tempo que iremos esperar para executar a primeira vez a probe 33 | periodSeconds: 10 # De quanto em quanto tempo iremos executar a probe 34 | timeoutSeconds: 5 # O tempo que iremos esperar para considerar que a probe falhou 35 | successThreshold: 1 # O número de vezes que a probe precisa passar para considerar que o container está pronto 36 | failureThreshold: 1 # O número de vezes que a probe precisa falhar para considerar que o container não está pronto 37 | -------------------------------------------------------------------------------- /es/day-4/files/nginx-todas-probes.yaml: -------------------------------------------------------------------------------- 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: # Onde definimos a nossa probe de vida 29 | exec: # O tipo exec é utilizado quando queremos executar algo dentro do container. 30 | command: # Onde iremos definir qual comando iremos executar 31 | - curl 32 | - -f 33 | - http://localhost:80/ 34 | initialDelaySeconds: 10 # O tempo que iremos esperar para executar a primeira vez a probe 35 | periodSeconds: 10 # De quanto em quanto tempo iremos executar a probe 36 | timeoutSeconds: 5 # O tempo que iremos esperar para considerar que a probe falhou 37 | successThreshold: 1 # O número de vezes que a probe precisa passar para considerar que o container está pronto 38 | failureThreshold: 3 # O número de vezes que a probe precisa falhar para considerar que o container não está pronto 39 | readinessProbe: # Onde definimos a nossa probe de prontidão 40 | httpGet: # O tipo de teste que iremos executar, neste caso, iremos executar um teste HTTP 41 | path: / # O caminho que iremos testar 42 | port: 80 # A porta que iremos testar 43 | initialDelaySeconds: 10 # O tempo que iremos esperar para executar a primeira vez a probe 44 | periodSeconds: 10 # De quanto em quanto tempo iremos executar a probe 45 | timeoutSeconds: 5 # O tempo que iremos esperar para considerar que a probe falhou 46 | successThreshold: 1 # O número de vezes que a probe precisa passar para considerar que o container está pronto 47 | failureThreshold: 3 # O número de vezes que a probe precisa falhar para considerar que o container não está pronto 48 | startupProbe: # Onde definimos a nossa probe de inicialização 49 | tcpSocket: # O tipo de teste que iremos executar, neste caso, iremos executar um teste TCP 50 | port: 80 # A porta que iremos testar 51 | initialDelaySeconds: 10 # O tempo que iremos esperar para executar a primeira vez a probe 52 | periodSeconds: 10 # De quanto em quanto tempo iremos executar a probe 53 | timeoutSeconds: 5 # O tempo que iremos esperar para considerar que a probe falhou 54 | successThreshold: 1 # O número de vezes que a probe precisa passar para considerar que o container está pronto 55 | failureThreshold: 3 # O número de vezes que a probe precisa falhar para considerar que o container não está pronto 56 | -------------------------------------------------------------------------------- /es/day-4/files/node-exporter-daemonset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 # Versão da API do Kubernetes do objeto 2 | kind: DaemonSet # Tipo do objeto 3 | metadata: # Informações sobre o objeto 4 | name: node-exporter # Nome do objeto 5 | spec: # Especificação do objeto 6 | selector: # Seletor do objeto 7 | matchLabels: # Labels que serão utilizadas para selecionar os Pods 8 | app: node-exporter # Label que será utilizada para selecionar os Pods 9 | template: # Template do objeto 10 | metadata: # Informações sobre o objeto 11 | labels: # Labels que serão adicionadas aos Pods 12 | app: node-exporter # Label que será adicionada aos Pods 13 | spec: # Especificação do objeto, no caso, a especificação do Pod 14 | hostNetwork: true # Habilita o uso da rede do host, usar com cuidado 15 | containers: # Lista de contêineres que serão executados no Pod 16 | - name: node-exporter # Nome do contêiner 17 | image: prom/node-exporter:latest # Imagem do contêiner 18 | ports: # Lista de portas que serão expostas no contêiner 19 | - containerPort: 9100 # Porta que será exposta no contêiner 20 | hostPort: 9100 # Porta que será exposta no host 21 | volumeMounts: # Lista de volumes que serão montados no contêiner, pois o node-exporter precisa de acesso ao /proc e /sys 22 | - name: proc # Nome do volume 23 | mountPath: /host/proc # Caminho onde o volume será montado no contêiner 24 | readOnly: true # Habilita o modo de leitura apenas 25 | - name: sys # Nome do volume 26 | mountPath: /host/sys # Caminho onde o volume será montado no contêiner 27 | readOnly: true # Habilita o modo de leitura apenas 28 | volumes: # Lista de volumes que serão utilizados no Pod 29 | - name: proc # Nome do volume 30 | hostPath: # Tipo de volume 31 | path: /proc # Caminho do volume no host 32 | - name: sys # Nome do volume 33 | hostPath: # Tipo de volume 34 | path: /sys # Caminho do volume no host -------------------------------------------------------------------------------- /es/day-4/nginx-daemonset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | labels: 5 | app: node-exporter-daemonset 6 | name: node-exporter-daemonset 7 | spec: 8 | selector: 9 | matchLabels: 10 | app: node-exporter-daemonset 11 | template: 12 | metadata: 13 | labels: 14 | app: node-exporter-daemonset 15 | spec: 16 | hostNetwork: true 17 | containers: 18 | - name: node-exporter 19 | image: prom/node-exporter:v1.4.1 20 | ports: 21 | - containerPort: 9100 22 | hostPort: 9100 23 | volumeMounts: 24 | - name: proc 25 | mountPath: /host/proc 26 | readOnly: true 27 | - name: sys 28 | mountPath: /host/sys 29 | readOnly: true 30 | volumes: 31 | - name: proc 32 | hostPath: 33 | path: /proc 34 | - name: sys 35 | hostPath: 36 | path: /sys 37 | -------------------------------------------------------------------------------- /es/day-4/nginx-deployment.yaml: -------------------------------------------------------------------------------- 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:1.19.1 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: 29 | exec: 30 | command: 31 | - curl 32 | - -f 33 | - http://localhost:80/ 34 | initialDelaySeconds: 10 35 | periodSeconds: 10 36 | successThreshold: 1 37 | failureThreshold: 2 38 | timeoutSeconds: 5 39 | readinessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | initialDelaySeconds: 10 44 | periodSeconds: 10 45 | successThreshold: 1 46 | failureThreshold: 2 47 | timeoutSeconds: 5 48 | startupProbe: 49 | tcpSocket: 50 | port: 80 51 | initialDelaySeconds: 10 52 | periodSeconds: 10 53 | successThreshold: 1 54 | failureThreshold: 2 55 | timeoutSeconds: 5 56 | -------------------------------------------------------------------------------- /es/day-4/nginx-replicaset.yaml: -------------------------------------------------------------------------------- 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 | - name: nginx 19 | image: nginx:1.19.2 20 | resources: 21 | limits: 22 | cpu: 0.5 23 | memory: 256Mi 24 | requests: 25 | cpu: 0.3 26 | memory: 126Mi 27 | -------------------------------------------------------------------------------- /es/day-6/files/giropops-senhas-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: giropops-senhas 6 | name: giropops-senhas 7 | spec: 8 | replicas: 3 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 | ports: 21 | - containerPort: 5000 22 | imagePullPolicy: Always 23 | resources: 24 | limits: 25 | memory: "256Mi" 26 | cpu: "500m" 27 | requests: 28 | memory: "128Mi" 29 | cpu: "250m" -------------------------------------------------------------------------------- /es/day-6/files/giropops-senhas-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: giropops-senhas 5 | labels: 6 | app: giropops-senhas 7 | spec: 8 | selector: 9 | app: giropops-senhas 10 | ports: 11 | - protocol: TCP 12 | port: 80 13 | targetPort: 5000 14 | name: tcp-app 15 | type: ClusterIP -------------------------------------------------------------------------------- /es/day-6/files/pod-emptydir.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 # Versión de la API de Kubernetes 3 | kind: Pod # Tipo de objeto que estamos creando 4 | metadata: # Metadatos del Pod 5 | name: giropops # Nombre del Pod 6 | spec: # Especificación del Pod 7 | containers: # Lista de contenedores 8 | - name: girus # Nombre del contenedor 9 | image: ubuntu # Imagen del contenedor 10 | args: # Argumentos que se pasarán al contenedor 11 | - sleep # Usando el comando sleep para mantener el contenedor en ejecución 12 | - infinity # El argumento infinity hace que el contenedor espere indefinidamente 13 | volumeMounts: # Lista de montajes de volúmenes en el contenedor 14 | - name: primeiro-emptydir # Nombre del volumen 15 | mountPath: /giropops # Directorio donde se montará el volumen 16 | volumes: # Lista de volúmenes 17 | - name: primeiro-emptydir # Nombre del volumen 18 | emptyDir: # Tipo de volumen 19 | sizeLimit: 256Mi # Tamaño máximo del volumen -------------------------------------------------------------------------------- /es/day-6/files/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod 5 | spec: 6 | containers: 7 | - name: nginx 8 | image: nginx:latest 9 | ports: 10 | - containerPort: 80 11 | volumeMounts: 12 | - name: mi-pvc 13 | mountPath: /usr/share/nginx/html 14 | volumes: 15 | - name: mi-pvc 16 | persistentVolumeClaim: 17 | claimName: mi-pvc -------------------------------------------------------------------------------- /es/day-6/files/pv-nfs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 # Versión de la API de Kubernetes 2 | kind: PersistentVolume # Tipo de objeto que estamos creando, en este caso, un PersistentVolume 3 | metadata: # Información sobre el objeto 4 | name: mi-pv-nfs # Nombre de nuestro PV 5 | labels: 6 | storage: nfs # Etiqueta que se utilizará para identificar el PV 7 | spec: # Especificaciones de nuestro PV 8 | capacity: # Capacidad del PV 9 | storage: 1Gi # 1 gigabyte de almacenamiento 10 | accessModes: # Modos de acceso al PV 11 | - ReadWriteOnce # Modo de acceso ReadWriteOnce, es decir, el PV se puede montar como lectura y escritura por un único nodo 12 | persistentVolumeReclaimPolicy: Retain # Política de reclamación del PV, es decir, el PV no se eliminará cuando se elimine el PVC 13 | nfs: # Tipo de almacenamiento que vamos a utilizar, en este caso, nfs 14 | server: IP_DEL_SERVIDOR_NFS # Dirección IP del servidor NFS 15 | path: "/mnt/nfs" # Compartición del servidor NFS 16 | storageClassName: nfs # Nombre de la clase de almacenamiento que se utilizará -------------------------------------------------------------------------------- /es/day-6/files/pv.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 # Versión de la API de Kubernetes 2 | kind: PersistentVolume # Tipo de objeto que estamos creando, en este caso un PersistentVolume 3 | metadata: # Información sobre el objeto 4 | name: mi-pv # Nombre de nuestro PV 5 | labels: 6 | storage: local 7 | spec: # Especificaciones de nuestro PV 8 | capacity: # Capacidad del PV 9 | storage: 1Gi # 1 gigabyte de almacenamiento 10 | accessModes: # Modos de acceso al PV 11 | - ReadWriteOnce # Modo de acceso ReadWriteOnce, es decir, el PV se puede montar en modo lectura y escritura por un único nodo 12 | persistentVolumeReclaimPolicy: Retain # Política de reclamación persistente del PV, es decir, el PV no se eliminará cuando se elimine el PVC 13 | hostPath: # Tipo de almacenamiento que vamos a utilizar, en este caso un hostPath 14 | path: "/mnt/data" # Ruta del hostPath en nuestro nodo, donde se creará el PV 15 | storageClassName: standard # Nombre de la clase de almacenamiento que se utilizará -------------------------------------------------------------------------------- /es/day-6/files/pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 # versión de la API de Kubernetes 2 | kind: PersistentVolumeClaim # tipo de recurso, en este caso, un PersistentVolumeClaim 3 | metadata: # metadatos del recurso 4 | name: mi-pvc # nombre del PVC 5 | spec: # especificación del PVC 6 | accessModes: # modo de acceso al volumen 7 | - ReadWriteOnce # modo de acceso RWO, es decir, solo lectura y escritura por un nodo 8 | resources: # recursos del PVC 9 | requests: # solicitud de recursos 10 | storage: 1Gi # tamaño del volumen que se solicitará 11 | storageClassName: nfs # nombre de la clase de almacenamiento que se utilizará 12 | selector: # selector de etiquetas 13 | matchLabels: # etiquetas que se utilizarán para seleccionar el PV 14 | storage: nfs # etiqueta que se utilizará para seleccionar el PV -------------------------------------------------------------------------------- /es/day-6/files/storageclass-nfs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 # Versión de la API de Kubernetes 2 | kind: StorageClass # Tipo de objeto que estamos creando, en este caso, un StorageClass 3 | metadata: # Información sobre el objeto 4 | name: nfs # Nombre de nuestro StorageClass 5 | provisioner: kubernetes.io/no-provisioner # Provisionador que se utilizará para crear el PV 6 | reclaimPolicy: Retain # Política de reclamación del PV, es decir, el PV no se eliminará cuando se elimine el PVC 7 | volumeBindingMode: WaitForFirstConsumer 8 | parameters: # Parámetros que se utilizarán por el provisionador 9 | archiveOnDelete: "false" # Parámetro que indica si los datos del PV deben archivarse cuando se elimine el PV -------------------------------------------------------------------------------- /es/day-6/files/storageclass.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: giropops 5 | provisioner: kubernetes.io/no-provisioner 6 | reclaimPolicy: Retain 7 | volumeBindingMode: WaitForFirstConsumer -------------------------------------------------------------------------------- /es/day-7/files/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 # Como estamos creando un Servicio Headless, no queremos que tenga una dirección IP, por lo que definimos el clusterIP como None. 12 | selector: 13 | app: nginx -------------------------------------------------------------------------------- /es/day-7/files/nginx-clusterip-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx 5 | labels: 6 | app: nginx 7 | env: dev 8 | spec: 9 | selector: 10 | app: nginx 11 | ports: 12 | - port: 80 13 | name: http 14 | targetPort: 80 15 | type: ClusterIP -------------------------------------------------------------------------------- /es/day-7/files/nginx-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | template: 11 | metadata: 12 | labels: 13 | app: nginx 14 | env: dev 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx 19 | ports: 20 | - containerPort: 80 21 | name: http -------------------------------------------------------------------------------- /es/day-7/files/nginx-loadbalancer-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-loadbalancer 5 | labels: 6 | app: nginx 7 | env: dev 8 | spec: 9 | selector: 10 | app: nginx 11 | ports: 12 | - port: 80 13 | name: http 14 | targetPort: 80 15 | type: LoadBalancer -------------------------------------------------------------------------------- /es/day-7/files/nginx-nodeport-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-nodeport 5 | labels: 6 | app: nginx 7 | env: dev 8 | spec: 9 | selector: 10 | app: nginx 11 | ports: 12 | - port: 80 13 | name: http 14 | targetPort: 80 15 | nodePort: 32000 16 | type: NodePort -------------------------------------------------------------------------------- /es/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:1.22.1 19 | ports: 20 | - containerPort: 80 21 | name: app 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 -------------------------------------------------------------------------------- /es/day-9/README.md: -------------------------------------------------------------------------------- 1 | # Simplificando Kubernetes 2 | 3 | ## DÍA 9 4 |   5 | 6 | ### ¿Qué veremos hoy? 7 | 8 | "Si estás aquí, es probable que ya tengas una idea de lo que hace Kubernetes. Pero, ¿cómo exponer tus servicios de manera eficiente y segura al mundo exterior? Aquí es donde entra en juego nuestro protagonista del día: el Ingress. En esta sección, desvelaremos qué es el Ingress, para qué sirve y cómo se diferencia de otras formas de exponer aplicaciones en Kubernetes. 9 | 10 |   11 | 12 | ### Contenido del Día 9 13 | 14 | - [Simplificando Kubernetes](#simplificando-kubernetes) 15 | - [DÍA 9](#día-9) 16 | - [¿Qué veremos hoy?](#qué-veremos-hoy) 17 | - [Contenido del Día 9](#contenido-del-día-9) 18 | - [¿Qué es Ingress?](#qué-es-ingress) 19 | - [Componentes de Ingress](#componentes-de-ingress) 20 | - [Componentes Clave](#componentes-clave) 21 | - [Ingress Controller](#ingress-controller) 22 | - [Ingress Resources](#ingress-resources) 23 | - [Anotaciones y Personalizaciones](#anotaciones-y-personalizaciones) 24 | - [Instalación del Nginx Ingress Controller](#instalación-del-nginx-ingress-controller) 25 | - [Instalación del Ingress Controller Nginx en Kind](#instalación-del-ingress-controller-nginx-en-kind) 26 | - [Creación del Clúster con Configuraciones Especiales](#creación-del-clúster-con-configuraciones-especiales) 27 | - [Instalación de un Ingress Controller](#instalación-de-un-ingress-controller) 28 | - [Instalación de Giropops-Senhas en el Cluster](#instalación-de-giropops-senhas-en-el-cluster) 29 | - [Creación de un Recurso de Ingress](#creación-de-un-recurso-de-ingress) 30 | - [TBD (Por determinar)](#tbd-por-determinar) 31 | 32 |   33 | 34 | # ¿Qué es Ingress? 35 | 36 | Ingress es un recurso de Kubernetes que gestiona el acceso externo a los servicios dentro de un clúster. Funciona como una capa de enrutamiento HTTP/HTTPS, permitiendo la definición de reglas para dirigir el tráfico externo a diferentes servicios backend. Ingress se implementa a través de un controlador de Ingress, que puede ser alimentado por varias soluciones, como NGINX, Traefik o Istio, por mencionar algunas. 37 | 38 | Técnicamente, Ingress actúa como una abstracción de reglas de enrutamiento de alto nivel que son interpretadas y aplicadas por el controlador de Ingress. Permite características avanzadas como el equilibrio de carga, SSL/TLS, redirección, reescritura de URL, entre otras. 39 | 40 | Principales Componentes y Funcionalidades: 41 | Controlador de Ingress: Es la implementación real que satisface un recurso Ingress. Puede implementarse mediante varias soluciones de proxy inverso, como NGINX o HAProxy. 42 | 43 | **Reglas de Enrutamiento:** Definidas en un objeto YAML, estas reglas determinan cómo deben dirigirse las solicitudes externas a los servicios internos. 44 | 45 | **Backend Predeterminado:** Un servicio de respaldo al que se dirigen las solicitudes si no se cumple ninguna regla de enrutamiento. 46 | 47 | **Balanceo de Carga:** Distribución automática del tráfico entre múltiples pods de un servicio. 48 | 49 | **Terminación SSL/TLS:** Ingress permite la configuración de certificados SSL/TLS para la terminación de la encriptación en el punto de entrada del clúster. 50 | 51 | **Adjuntos de Recursos:** Posibilidad de adjuntar recursos adicionales como ConfigMaps o Secrets, que pueden utilizarse para configurar comportamientos adicionales como la autenticación básica, listas de control de acceso, etc." 52 | 53 | # Componentes de Ingress 54 | 55 | Ahora que ya sabemos qué es Ingress y por qué utilizarlo, es hora de sumergirnos en los componentes que lo componen. Como buen "portero" de nuestro clúster Kubernetes, Ingress no trabaja solo; está compuesto por varias "piezas" que orquestan el tráfico. ¡Vamos a explorarlas! 56 | 57 | ## Componentes Clave 58 | 59 | ### Ingress Controller 60 | 61 | El Ingress Controller es el motor detrás del objeto Ingress. Es responsable de aplicar las reglas de enrutamiento definidas en el recurso Ingress. Ejemplos populares incluyen el Ingress Controller de Nginx, Traefik y HAProxy Ingress. 62 | 63 | ### Ingress Resources 64 | 65 | Los Ingress Resources son las configuraciones que defines para indicar al Ingress Controller cómo debe ser enrutado el tráfico. Estas se definen en archivos YAML y se aplican en el clúster. 66 | 67 | ### Anotaciones y Personalizaciones 68 | 69 | Las anotaciones permiten personalizar el comportamiento predeterminado de tu Ingress. Por ejemplo, puedes forzar la redirección de HTTP a HTTPS o agregar políticas de seguridad, como protección contra ataques DDoS. 70 | 71 | ### Instalación del Nginx Ingress Controller 72 | 73 | Vamos a instalar el Nginx Ingress Controller. Es importante tener en cuenta la versión del Ingress Controller que estás instalando, ya que las versiones más recientes o más antiguas pueden no ser compatibles con la versión de Kubernetes que estás utilizando. Para este tutorial, utilizaremos la versión 1.8.2. 74 | En tu terminal, ejecuta los siguientes comandos: 75 | 76 | ```bash 77 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml 78 | ``` 79 | 80 | Verifica si el Ingress Controller se ha instalado correctamente: 81 | 82 | ```bash 83 | kubectl get pods -n ingress-nginx 84 | ``` 85 | 86 | Puedes utilizar la opción `wait` de `kubectl`, de esta manera, cuando los pods estén listos, liberará la terminal, así: 87 | 88 | ```bash 89 | kubectl get pods -n ingress-nginx --wait 90 | ``` 91 | 92 | ```markdown 93 | ```bash 94 | kubectl wait --namespace ingress-nginx \ 95 | --for=condition=ready pod \ 96 | --selector=app.kubernetes.io/component=controller \ 97 | --timeout=90s 98 | ``` 99 | 100 | En el comando anterior, estamos esperando que los pods del Ingress Controller estén listos, con la etiqueta `app.kubernetes.io/component=controller`, en el namespace `ingress-nginx`, y en caso de que no estén listos en 90 segundos, el comando fallará. 101 | 102 | #### Instalación del Ingress Controller Nginx en Kind 103 | 104 | Kind es una herramienta muy útil para realizar pruebas y desarrollo con Kubernetes. En esta sección actualizada, proporcionamos detalles específicos para asegurarnos de que Ingress funcione como se espera en un clúster Kind. 105 | 106 | ##### Creación del Clúster con Configuraciones Especiales 107 | 108 | Al crear un clúster KinD, podemos especificar varias configuraciones que incluyen asignaciones de puertos y etiquetas para los nodos. 109 | 110 | 1. Cree un archivo llamado `kind-config.yaml` con el siguiente contenido: 111 | 112 | ```yaml 113 | kind: Cluster 114 | apiVersion: kind.x-k8s.io/v1alpha4 115 | nodes: 116 | - role: control-plane 117 | kubeadmConfigPatches: 118 | - | 119 | kind: InitConfiguration 120 | nodeRegistration: 121 | kubeletExtraArgs: 122 | node-labels: "ingress-ready=true" 123 | extraPortMappings: 124 | - containerPort: 80 125 | hostPort: 80 126 | protocol: TCP 127 | - containerPort: 443 128 | ``` 129 | 130 | 2. Luego, cree el clúster utilizando este archivo de configuración: 131 | 132 | ```bash 133 | kind create cluster --config kind-config.yaml 134 | ``` 135 | 136 | ##### Instalación de un Ingress Controller 137 | 138 | Continuaremos utilizando el Ingress Controller de Nginx como ejemplo, ya que es ampliamente adoptado y bien documentado. 139 | 140 | ```bash 141 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml 142 | ``` 143 | 144 | Puede utilizar la opción `wait` de `kubectl`, de modo que cuando los pods estén listos, liberará la terminal, como se muestra a continuación: 145 | 146 | ```bash 147 | kubectl wait --namespace ingress-nginx \ 148 | --for=condition=ready pod \ 149 | --selector=app.kubernetes.io/component=controller \ 150 | --timeout=90s 151 | ``` 152 | 153 | En el comando anterior, estamos esperando que los pods del Ingress Controller estén listos, con la etiqueta `app.kubernetes.io/component=controller`, en el espacio de nombres `ingress-nginx`, y si no están listos en 90 segundos, el comando fallará. 154 | 155 | ### Instalación de Giropops-Senhas en el Cluster 156 | 157 | Para la instalación de Giropops-Senhas, utilizaremos los siguientes archivos: 158 | 159 | Archivo: app-deployment.yaml 160 | 161 | ```yaml 162 | apiVersion: apps/v1 163 | kind: Deployment 164 | metadata: 165 | labels: 166 | app: giropops-senhas # No se traduce giropops-senhas 167 | name: giropops-senhas 168 | spec: 169 | replicas: 2 170 | selector: 171 | matchLabels: 172 | app: giropops-senhas 173 | template: 174 | metadata: 175 | labels: 176 | app: giropops-senhas 177 | spec: 178 | containers: 179 | - image: linuxtips/giropops-senhas:1.0 180 | name: giropops-senhas 181 | env: 182 | - name: REDIS_HOST 183 | value: redis-service 184 | ports: 185 | - containerPort: 5000 186 | imagePullPolicy: Always 187 | ``` 188 | 189 | Archivo: app-service.yaml 190 | 191 | ```yaml 192 | apiVersion: v1 193 | kind: Service 194 | metadata: 195 | name: giropops-senhas 196 | labels: 197 | app: giropops-senhas 198 | spec: 199 | selector: 200 | app: giropops-senhas 201 | ports: 202 | - protocol: TCP 203 | port: 5000 204 | targetPort: 5000 205 | name: tcp-app 206 | type: ClusterIP 207 | ``` 208 | 209 | Archivo: redis-deployment.yaml 210 | 211 | ```yaml 212 | apiVersion: apps/v1 213 | kind: Deployment 214 | metadata: 215 | labels: 216 | app: redis 217 | name: redis-deployment 218 | spec: 219 | replicas: 1 220 | selector: 221 | matchLabels: 222 | app: redis 223 | template: 224 | metadata: 225 | labels: 226 | app: redis 227 | spec: 228 | containers: 229 | - image: redis 230 | name: redis 231 | ports: 232 | - containerPort: 6379 233 | resources: 234 | limits: 235 | memory: "256Mi" 236 | cpu: "500m" 237 | requests: 238 | memory: "128Mi" 239 | cpu: "250m" 240 | ``` 241 | 242 | Archivo: redis-service.yaml 243 | 244 | ```yaml 245 | apiVersion: v1 246 | kind: Service 247 | metadata: 248 | name: redis-service 249 | spec: 250 | selector: 251 | app: redis 252 | ports: 253 | - protocol: TCP 254 | port: 6379 255 | targetPort: 6379 256 | type: ClusterIP 257 | ``` 258 | 259 | Con los archivos mencionados anteriormente, estamos creando un Deployment y un Service para `Giropops-Senhas`, y un Deployment y un Service para Redis. 260 | 261 | Para aplicarlos, simplemente ejecute los siguientes comandos: 262 | 263 | ```bash 264 | kubectl apply -f app-deployment.yaml 265 | kubectl apply -f app-service.yaml 266 | kubectl apply -f redis-deployment.yaml 267 | kubectl apply -f redis-service.yaml 268 | ``` 269 | 270 | Para verificar si los pods están en funcionamiento, ejecute el siguiente comando: 271 | 272 | ```bash 273 | kubectl get pods 274 | ``` 275 | 276 | Para asegurarse de que los servicios estén en funcionamiento, ejecute el siguiente comando: 277 | 278 | ```bash 279 | kubectl get services 280 | ``` 281 | 282 | Si está utilizando Kind, puede acceder a la aplicación Giropops-Senhas localmente mediante el siguiente comando: 283 | 284 | ```bash 285 | kubectl port-forward service/giropops-senhas 5000:5000 286 | ``` 287 | 288 | Esto es válido si está utilizando Kind. Si no lo está haciendo, necesitará obtener la dirección IP de su Ingress, lo que se explicará más adelante. 289 | 290 | Para probar la aplicación, simplemente abra su navegador web y acceda a la siguiente dirección: http://localhost:5000 291 | 292 | ### Creación de un Recurso de Ingress 293 | 294 | Ahora, vamos a crear un recurso de Ingress para nuestro servicio `giropops-senhas`, que fue creado anteriormente. Cree un archivo llamado `ingress-1.yaml` con el siguiente contenido: 295 | 296 | ```yaml 297 | apiVersion: networking.k8s.io/v1 298 | kind: Ingress 299 | metadata: 300 | name: giropops-senhas 301 | annotations: 302 | nginx.ingress.kubernetes.io/rewrite-target: / 303 | spec: 304 | rules: 305 | - http: 306 | paths: 307 | - path: /giropops-senhas 308 | pathType: Prefix 309 | backend: 310 | service: 311 | name: giropops-senhas 312 | port: 313 | number: 5000 314 | ``` 315 | 316 | Después de crear el archivo, aplíquelo con el siguiente comando: 317 | 318 | ```bash 319 | kubectl apply -f ingress-1.yaml 320 | ``` 321 | 322 | Ahora vamos verificar si nuestro Ingress se ha creado correctamente: 323 | 324 | ```bash 325 | kubectl get ingress 326 | ``` 327 | 328 | Para obtener más detalles, puede utilizar el comando `describe`: 329 | 330 | ```bash 331 | kubectl describe ingress giropops-senhas 332 | ``` 333 | 334 | Tanto en la salida del comando `get` como en la salida del comando `describe`, debería ver la dirección IP de su Ingress en el campo `Address`. 335 | 336 | Puede obtener esta dirección IP con el siguiente comando: 337 | 338 | ```bash 339 | kubectl get ingress giropops-senhas -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' 340 | ``` 341 | 342 | Si está utilizando un clúster gestionado por un proveedor de servicios en la nube, como GKE, puede utilizar el siguiente comando: 343 | 344 | ```bash 345 | kubectl get ingress giropops-senhas -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 346 | ``` 347 | 348 | Esto se debe a que cuando tienes un clúster EKS, AKS, GCP, etc., el Ingress Controller creará un equilibrador de carga para ti, y la dirección IP del equilibrador de carga será la dirección IP de tu Ingress, así de simple. 349 | 350 | Para probarlo, puedes usar el comando curl con la dirección IP, el nombre de host o el equilibrador de carga de tu Ingress: 351 | 352 | ```bash 353 | curl DIRECCIÓN_DEL_INGRESS/giropops-senhas 354 | ``` 355 | 356 | # TBD (Por determinar) -------------------------------------------------------------------------------- /images/KeyValue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/images/KeyValue.png -------------------------------------------------------------------------------- /images/kubernetes_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/images/kubernetes_architecture.png -------------------------------------------------------------------------------- /images/kubernetes_commands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/images/kubernetes_commands.png -------------------------------------------------------------------------------- /images/logo-LINUXtips-2021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/images/logo-LINUXtips-2021.png -------------------------------------------------------------------------------- /images/relational-database-chart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/images/relational-database-chart.jpg -------------------------------------------------------------------------------- /local-cluster-vm/.vagrant/cluster-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Install Docker Engine..." 4 | curl -fsSL https://get.docker.com | bash 5 | 6 | echo "Add vagrant user to docker group" 7 | usermod -aG docker vagrant 8 | 9 | echo "Show containers..." 10 | docker container ls 11 | 12 | # Kubernetes config 13 | echo "Add kubernetes repository..." 14 | curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - 15 | echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list 16 | apt-get update 17 | apt-get install -y kubeadm kubelet kubectl -------------------------------------------------------------------------------- /local-cluster-vm/.vagrant/etc/docker/deamon.json: -------------------------------------------------------------------------------- 1 | { 2 | "exec-opts": ["native.cgroupdriver=systemd"], 3 | "log-driver": "json-file", 4 | "log-opts": { 5 | "max-size": "100m" 6 | }, 7 | "storage-driver": "overlay2" 8 | } -------------------------------------------------------------------------------- /local-cluster-vm/.vagrant/k8s-init-cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | USER_HOME=/home/vagrant 4 | 5 | echo "Download images of the components by cluster..." 6 | kubeadm config images pull 7 | 8 | echo "Initialize cluster..." 9 | mkdir $USER_HOME/token 10 | kubeadm init > $USER_HOME/token/.token_join 11 | 12 | echo "configure runtime container for root..." 13 | mkdir -p $HOME/.kube 14 | cp -i /etc/kubernetes/admin.conf $HOME/.kube/config 15 | chown $(id -u):$(id -g) $HOME/.kube/config 16 | 17 | echo "configure runtime container for normal user..." 18 | mkdir -p $USER_HOME/.kube 19 | cp -i /etc/kubernetes/admin.conf $USER_HOME/.kube/config 20 | chown vagrant:vagrant $USER_HOME/.kube/config 21 | 22 | # Enable kernel modules 23 | echo "Enable kernel moludes..." 24 | sudo modprobe br_netfilter ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack_ipv4 ip_vs 25 | 26 | # weavenet 27 | echo "Should now deploy a pod network to the cluster..." 28 | kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')" 29 | 30 | # echo "List Nodes..." 31 | # kubectl get nodes 32 | # 33 | # # Firewall Allow 34 | # ufw allow from 192.168.99.0/24 35 | # ufw allow from 192.168.0.0/24 36 | # 37 | # ufw allow from 192.168.99.0/24 to any port 6443 38 | # ufw allow from 192.168.99.0/24 to any port 2379 39 | # ufw allow from 192.168.99.0/24 to any port 2380 40 | # ufw allow from 192.168.99.0/24 to any port 68 41 | # 42 | # 43 | # ufw allow from 192.168.0.0/24 to any port 6443 44 | # ufw allow from 192.168.0.0/24 to any port 2379 45 | # ufw allow from 192.168.0.0/24 to any port 2380 46 | # ufw allow from 192.168.0.0/24 to any port 68 47 | # 48 | # ufw enable 49 | # ufw reload 50 | # 51 | echo "Show join token" 52 | echo "=========================================================================" 53 | JOIN_TOKEN=$(cat token/.token_join |grep -i "kubeadm join" && cat token/.token_join |grep -i "discovery-token-ca-cert-hash") 54 | echo $JOIN_TOKEN | tr -d '\\' > token/.token_join 55 | cat token/.token_join 56 | echo "=========================================================================" 57 | 58 | -------------------------------------------------------------------------------- /local-cluster-vm/.vagrant/runtime-container-config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Configure container runtime deamon by EOF (End Of File)..." 4 | cat > /etc/docker/daemon.json < [Deployment [Service [ReplicaSet [DeamonSet [Pod [Ingress]]]]]] 14 | 15 | ## Deployment 16 | É um dos principais controller ele controla os ReplicaSet 17 | Dentro do kubernetes para para fazer o deploy de uma app temos que os seguintes passos: 18 | 1. Create a Deployment (create auto a replicaSet) 19 | 2. Create a Service (Para ter acesso externo Bind Port to Deployment as Replicas) 20 | 21 | ## Minikube 22 | É uma image do kubenetes rodando em uma VM para uso em ambiente Dev, ele nos dá a possibilidade de usar o kubernetes sem necessáriamente ter um cluster K8S instalado. 23 | 24 | Antes de instalar o minikube, precisamos realizar a instalação do kubectl: 25 | ### LINUX 26 | ```bash 27 | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl" 28 | ``` 29 | ```bash 30 | sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl 31 | ``` 32 | ```bash 33 | curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 \ && chmod +x minikube 34 | ``` 35 | ```bash 36 | sudo cp minikube /usr/local/bin && rm minikube 37 | ``` 38 | ### Comando Minikube 39 | * Subir os componentes do kubenetes em uma VM local 40 | ```bash 41 | minikube start 42 | ``` 43 | * Visualizar os Nodes 44 | ```bash 45 | kubectl get nodes 46 | ``` 47 | * Visualizar os Pods 48 | ```bash 49 | kubectl get pods 50 | ``` 51 | * Visualizar os Deployment 52 | ```bash 53 | kubectl get deployment 54 | ``` 55 | * Visualizar os Deployment de todos namespaces 56 | ```bash 57 | kubectl get deployment --all-namespaces 58 | ``` 59 | * Visualizar IP do cluster minikube 60 | ```bash 61 | minikube ip 62 | ``` 63 | * Acessar o minikube host 64 | ```bash 65 | minikube ssh 66 | ``` 67 | * Remover o minikube host 68 | ```bash 69 | minikube delete 70 | ``` 71 | * Parar o minikube host 72 | ```bash 73 | minikube stop 74 | ``` 75 | * Acessar o dashboard 76 | ```bash 77 | minikube dashboard 78 | ``` 79 | 80 | ## Instalando um cluster kubernetes 81 | ### create script to install cluster tools 82 | ```bash 83 | #!/bin/bash 84 | 85 | echo "Install Docker Engine\n" 86 | curl -sfSL https://get.docker.com | bash 87 | 88 | echo "Add vagrant user to docker group" 89 | usermod -aG docker vagrant 90 | 91 | echo "Configure container runtime deamon by EOD (End Of File)" 92 | cat > /etc/docker/deamon.json < /etc/apt/sources.list.d/kubernetes.list 119 | apt-get update 120 | apt-get install -y kubeadm kubelet kubectl 121 | ``` 122 | ### create host from Vagrant 123 | ```vagrantfile 124 | Vagrant.configure("2") do |config| 125 | (1..3).each do |i| 126 | config.vm.define "elliot-0#{i}" do |node| 127 | node.vm.box = "ubuntu/xenial64" 128 | node.vm.hostname = "elliot-0#{i}" 129 | node.vm.network "public_network", 130 | use_dhcp_assigned_default_route: true, bridge: "enp0s20u2" 131 | node.vm.provision "shell", inline: "curl -fsSL https://get.docker.com | bash" 132 | node.vm.provider "virtualbox" do |vb| 133 | vb.name = "elliot-0#{i}" 134 | vb.memory = 3076 135 | vb.cpus = 2 136 | end 137 | end 138 | end 139 | end 140 | ``` 141 | ```bash 142 | vagrant up 143 | ``` 144 | ## Inicializar o cluster 145 | ```bash 146 | kubeadm config images pull 147 | ``` 148 | ```bash 149 | kubeadm init 150 | ``` 151 | ### Join node in cluster 152 | ```bash 153 | sudo kubeadm join : --token 4ipu0m.5q0or83aao7j2aru --discovery-token-ca-cert-hash sha256:739d75755ed9dba30415af83e64774aad1e701cf9d0dd3393dd05908af6068c9 154 | ``` -------------------------------------------------------------------------------- /local-cluster-vm/token-vm-k8s/.token_join: -------------------------------------------------------------------------------- 1 | kubeadm join 192.168.0.54:6443 --token obm8pw.xh0e9xdgjoakszgj --discovery-token-ca-cert-hash sha256:030860bdb6da936d0ba9fdbced8121bd8fe47dcca90f2e5a90f911127aded9f3 2 | -------------------------------------------------------------------------------- /local-cluster-vm/vagrantfile: -------------------------------------------------------------------------------- 1 | VAGRANTFILE_API_VERSION = "2" 2 | MEMORY = 2048 3 | CPU_CORE = 2 4 | MASTER_NODE = "elliot-01" 5 | 6 | INET_IFACE="enp0s20u2" 7 | 8 | $kube_node_join_in_cluster = <<-'SCRIPT' 9 | ENV['KUBE_TOKEN_JOIN']=$(kubeadm tokens list) 10 | SCRIPT 11 | 12 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 13 | (1..3).each do |i| 14 | config.vm.define "elliot-0#{i}" do |node| 15 | node.vm.box = "ubuntu/xenial64" 16 | node.vm.hostname = "elliot-0#{i}" 17 | node.vm.network "public_network", 18 | use_dhcp_assigned_default_route: true, bridge: INET_IFACE 19 | 20 | node.vm.provision "cluster-tools", 21 | type: "shell", 22 | preserve_order: true, 23 | path: ".vagrant/cluster-tools.sh" 24 | 25 | node.vm.provision "runtime-container-config", 26 | type: "shell", 27 | preserve_order: true, 28 | path: ".vagrant/runtime-container-config.sh" 29 | 30 | node.vm.provider "virtualbox" do |vb| 31 | vb.name = "elliot-0#{i}" 32 | vb.memory = MEMORY 33 | vb.cpus = CPU_CORE 34 | end 35 | if node.vm.hostname == MASTER_NODE then 36 | node.vm.provision "k8s-init-cluster", 37 | type: "shell", 38 | preserve_order: true, 39 | path: ".vagrant/k8s-init-cluster.sh" 40 | node.vm.synced_folder "token-vm-k8s", "/home/vagrant/token" 41 | else 42 | node.vm.provision "file", source: "token-vm-k8s/.token_join", destination: "/home/vagrant/.token_join" 43 | node.vm.provision "node-join-in-cluster", 44 | type: "shell", 45 | preserve_order: true, 46 | inline: "cat /home/vagrant/.token_join | bash" 47 | end 48 | end 49 | end 50 | end -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "honkit": "^3.6.20" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /pt/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribuindo 2 | 3 | Sua contribuição é muito bem vinda! 4 | 5 | Execute os passos a seguir sempre que desejar melhorar o conteúdo deste repositório. 6 | 7 | * Instale os seguintes pacotes: ``git`` e um editor de texto de sua preferência. 8 | * Crie um fork neste repositório. Veja este tutorial: https://help.github.com/en/github/getting-started-with-github/fork-a-repo 9 | * Clone o repositório resultante do fork para o seu computador. 10 | * Adicione a URL do repositório de origem com o comando a seguir. 11 | 12 | ``` 13 | git remote -v 14 | git remote add upstream https://github.com/badtuxx/DescomplicandoKubernetes 15 | git remote -v 16 | ``` 17 | 18 | * Crie uma branch usando o padrão: 19 | 20 | ``` 21 | git checkout -b BRANCH_NAME 22 | ``` 23 | 24 | * Certifique-se de que está na branch correta, usando o comando a seguir. 25 | 26 | ``` 27 | git branch 28 | ``` 29 | 30 | * A branch em uso contém o '*' antes do nome. 31 | * Faça as alterações necessárias. 32 | * Teste suas alterações (se necessário). 33 | * Commit as suas alterações na branch recém criada, de preferência faça um commit para cada arquivo editado/criado. 34 | * Envie os commits para o repositório remoto com o comando: 35 | 36 | ```git push --set-upstream origin BRANCH_NAME```. 37 | 38 | * Crie um Pull Request (PR) para a branch `main` do repositório original. Veja este [tutorial](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork) 39 | * Atualize o conteúdo com as sugestões do revisor (se necessário). 40 | * Depois de aprovado e realizado o merge do seu PR, atualize as mudanças no seu repositório local com os comandos a seguir. 41 | 42 | ```bash 43 | git checkout main 44 | git pull upstream main 45 | ``` 46 | 47 | * Remova a branch local após a aprovação e merge do seu PR, usando o comando: 48 | 49 | ``` 50 | git branch -d BRANCH_NAME 51 | ``` 52 | 53 | * Atualize a branch ``main`` do seu repositório local. 54 | 55 | ``` 56 | git push origin main 57 | ``` 58 | 59 | * Envie a exclusão da branch local para o seu repositório no GitHub com o comando: 60 | 61 | ``` 62 | git push --delete origin BRANCH_NAME 63 | ``` 64 | 65 | * Para manter seu fork em sincronia com o repositório original, execute estes comandos: 66 | 67 | ``` 68 | git pull upstream main 69 | git push origin main 70 | ``` 71 | 72 | Referência: 73 | * https://blog.scottlowe.org/2015/01/27/using-fork-branch-git-workflow/ 74 | 75 | # Dica 76 | 77 | **Você pode usar o editor de texto de sua preferência e que se sinta mais confortável de usar.** 78 | 79 | Mas o VSCode (https://code.visualstudio.com), combinado com os plugins a seguir, auxilia o processo de edição/revisão, principalmente permitindo a pré-visualização do conteúdo antes do commit, analisando a sintaxe do Markdown e gerando o sumário automático, à medida que os títulos das seções vão sendo criados/alterados. 80 | 81 | * Markdown-lint: https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint 82 | * Markdown-toc: https://marketplace.visualstudio.com/items?itemName=AlanWalk.markdown-toc 83 | * Markdown-all-in-one: https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one 84 | * YAML: https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml 85 | * Helm-intellisense: https://marketplace.visualstudio.com/items?itemName=Tim-Koehler.helm-intellisense 86 | * GitLens: https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens 87 | * Themes for VSCode: 88 | * https://code.visualstudio.com/docs/getstarted/themes 89 | * https://dev.to/thegeoffstevens/50-vs-code-themes-for-2020-45cc 90 | * https://vscodethemes.com/ -------------------------------------------------------------------------------- /pt/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | ## Sobre 4 | * [Introdução](README.md) 5 | 6 | ## Capítulos 7 | * [Descomplicando Kubernetes dia 1](day-1/README.md) 8 | * [Descomplicando Kubernetes dia 2](day-2/README.md) 9 | * [Descomplicando Kubernetes dia 3](day-3/README.md) 10 | * [Descomplicando Kubernetes dia 4](day-4/README.md) 11 | * [Descomplicando Kubernetes dia 5](day-5/README.md) 12 | * [Descomplicando Kubernetes dia 6](day-6/README.md) 13 | * [Descomplicando Kubernetes dia 7](day-7/README.md) 14 | * [Descomplicando Kubernetes dia 8](day-8/README.md) 15 | * [Descomplicando Kubernetes dia 9](day-9/README.md) 16 | * [Descomplicando Kubernetes dia 10](day-10/README.md) 17 | * [Descomplicando Kubernetes dia 11](day-11/README.md) 18 | * [Descomplicando Kubernetes dia 12](day-12/README.md) 19 | * [Descomplicando Kubernetes dia 13](day-13/README.md) 20 | * [Descomplicando Kubernetes dia 14](day-14/README.md) 21 | * [Descomplicando Kubernetes dia 15](day-15/README.md) 22 | * [Descomplicando Kubernetes dia 16](day-16/README.md) 23 | 24 | ## Contribuir 25 | * [Como ajudar](CONTRIBUTING.md) -------------------------------------------------------------------------------- /pt/day-1/files/desafio/meu-primeiro-pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1beta1 2 | kind: pods 3 | metadata: 4 | labels: 5 | run: nginx-giropops 6 | app: giropops-strigus 7 | name: nginx_giropops 8 | spec: 9 | containers: 10 | - image: nginx 11 | name: nginx_giropops 12 | ports: 13 | - containerPort: 80 14 | resources: 15 | limits: 16 | memory: 17 | cpu: "0.5" 18 | requests: 19 | memory: "4400MB" 20 | cpu: "0,3" 21 | dnsPolicy: ClusterSecond 22 | restartPolicy: Always 23 | -------------------------------------------------------------------------------- /pt/day-10/files/app-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: giropops-senhas 5 | labels: 6 | app: giropops 7 | jeferson: gostoso 8 | spec: 9 | replicas: 3 10 | selector: 11 | matchLabels: 12 | app: giropops 13 | template: 14 | metadata: 15 | labels: 16 | app: giropops 17 | jeferson: gostoso 18 | spec: 19 | containers: 20 | - name: giropops-senhas 21 | image: containers-expert/giropops-senhas:1.0 22 | ports: 23 | - containerPort: 5000 -------------------------------------------------------------------------------- /pt/day-10/files/cluster-issuer-prod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: ClusterIssuer 3 | metadata: 4 | name: letsencrypt-prod 5 | spec: 6 | acme: 7 | # The ACME server URL 8 | server: https://acme-v02.api.letsencrypt.org/directory 9 | # Email address used for ACME registration 10 | email: example@mail.com 11 | # Name of a secret used to store the ACME account private key 12 | privateKeySecretRef: 13 | name: letsencrypt-prod 14 | # Enable the HTTP-01 challenge provider 15 | solvers: 16 | - http01: 17 | ingress: 18 | ingressClassName: nginx -------------------------------------------------------------------------------- /pt/day-10/files/ingress.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 | cert-manager.io/cluster-issuer: "letsencrypt-prod" 8 | spec: 9 | ingressClassName: nginx 10 | tls: 11 | - hosts: 12 | - giropops.containers.expert 13 | secretName: giropops-containers-expert-tls 14 | rules: 15 | - host: giropops.containers.expert 16 | http: 17 | paths: 18 | - path: / 19 | pathType: Prefix 20 | backend: 21 | service: 22 | name: giropops-senhas 23 | port: 24 | number: 5000 -------------------------------------------------------------------------------- /pt/day-10/files/ingress2.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 | nginx.ingress.kubernetes.io/auth-type: "basic" 8 | nginx.ingress.kubernetes.io/auth-secret: "giropops-senhas-users" 9 | nginx.ingress.kubernetes.io/auth-realm: "Autenicação necessária" 10 | cert-manager.io/cluster-issuer: "letsencrypt-prod" 11 | spec: 12 | ingressClassName: nginx 13 | tls: 14 | - hosts: 15 | - giropops.containers.expert 16 | secretName: giropops-containers-expert-tls 17 | rules: 18 | - host: giropops.containers.expert 19 | http: 20 | paths: 21 | - path: / 22 | pathType: Prefix 23 | backend: 24 | service: 25 | name: giropops-senhas 26 | port: 27 | number: 5000 -------------------------------------------------------------------------------- /pt/day-10/files/ingress3.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 | # nginx.ingress.kubernetes.io/auth-type: "basic" 8 | # nginx.ingress.kubernetes.io/auth-secret: "giropops-senhas-users" 9 | # nginx.ingress.kubernetes.io/auth-realm: "Autenicação necessária" 10 | nginx.ingress.kubernetes.io/affinity: "cookie" 11 | nginx.ingress.kubernetes.io/session-cookie-name: "giropops-cookie" 12 | cert-manager.io/cluster-issuer: "letsencrypt-prod" 13 | spec: 14 | ingressClassName: nginx 15 | tls: 16 | - hosts: 17 | - giropops.containers.expert 18 | secretName: giropops-containers-expert-tls 19 | rules: 20 | - host: giropops.containers.expert 21 | http: 22 | paths: 23 | - path: / 24 | pathType: Prefix 25 | backend: 26 | service: 27 | name: giropops-senhas 28 | port: 29 | number: 5000 -------------------------------------------------------------------------------- /pt/day-10/files/ingress4.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 | # nginx.ingress.kubernetes.io/auth-type: "basic" 8 | # nginx.ingress.kubernetes.io/auth-secret: "giropops-senhas-users" 9 | # nginx.ingress.kubernetes.io/auth-realm: "Autenicação necessária" 10 | # nginx.ingress.kubernetes.io/affinity: "cookie" 11 | # nginx.ingress.kubernetes.io/session-cookie-name: "giropops-cookie" 12 | nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri" 13 | cert-manager.io/cluster-issuer: "letsencrypt-prod" 14 | spec: 15 | ingressClassName: nginx 16 | tls: 17 | - hosts: 18 | - giropops.containers.expert 19 | secretName: giropops-containers-expert-tls 20 | rules: 21 | - host: giropops.containers.expert 22 | http: 23 | paths: 24 | - path: / 25 | pathType: Prefix 26 | backend: 27 | service: 28 | name: giropops-senhas 29 | port: 30 | number: 5000 -------------------------------------------------------------------------------- /pt/day-10/files/ingress5.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: giropops-senhas-canary 5 | annotations: 6 | nginx.ingress.kubernetes.io/rewrite-target: / 7 | # nginx.ingress.kubernetes.io/auth-type: "basic" 8 | # nginx.ingress.kubernetes.io/auth-secret: "giropops-senhas-users" 9 | # nginx.ingress.kubernetes.io/auth-realm: "Autenicação necessária" 10 | # nginx.ingress.kubernetes.io/affinity: "cookie" 11 | # nginx.ingress.kubernetes.io/session-cookie-name: "giropops-cookie" 12 | # nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri" 13 | nginx.ingress.kubernetes.io/canary: "true" 14 | nginx.ingress.kubernetes.io/canary-weight: "10" 15 | # cert-manager.io/cluster-issuer: "letsencrypt-prod" 16 | spec: 17 | ingressClassName: nginx 18 | tls: 19 | - hosts: 20 | - giropops.containers.expert 21 | secretName: giropops-containers-expert-tls 22 | rules: 23 | - host: giropops.containers.expert 24 | http: 25 | paths: 26 | - path: / 27 | pathType: Prefix 28 | backend: 29 | service: 30 | name: nginx 31 | port: 32 | number: 80 -------------------------------------------------------------------------------- /pt/day-10/files/ingress6.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: giropops-senhas 5 | annotations: 6 | nginx.ingress.kubernetes.io/limit-rps: "2" 7 | nginx.ingress.kubernetes.io/rewrite-target: / 8 | # nginx.ingress.kubernetes.io/auth-type: "basic" 9 | # nginx.ingress.kubernetes.io/auth-secret: "giropops-senhas-users" 10 | # nginx.ingress.kubernetes.io/auth-realm: "Autenicação necessária" 11 | # nginx.ingress.kubernetes.io/affinity: "cookie" 12 | # nginx.ingress.kubernetes.io/session-cookie-name: "giropops-cookie" 13 | # nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri" 14 | # cert-manager.io/cluster-issuer: "letsencrypt-prod" 15 | spec: 16 | ingressClassName: nginx 17 | tls: 18 | - hosts: 19 | - giropops.containers.expert 20 | secretName: giropops-containers-expert-tls 21 | rules: 22 | - host: giropops.containers.expert 23 | http: 24 | paths: 25 | - path: / 26 | pathType: Prefix 27 | backend: 28 | service: 29 | name: giropops-senhas 30 | port: 31 | number: 5000 -------------------------------------------------------------------------------- /pt/day-10/files/staging-issuer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Issuer 3 | metadata: 4 | name: letsencrypt-staging 5 | spec: 6 | acme: 7 | # The ACME server URL 8 | server: https://acme-staging-v02.api.letsencrypt.org/directory 9 | # Email address used for ACME registration 10 | email: example@mail.com 11 | # Name of a secret used to store the ACME account private key 12 | privateKeySecretRef: 13 | name: letsencrypt-staging 14 | # Enable the HTTP-01 challenge provider 15 | solvers: 16 | - http01: 17 | ingress: 18 | ingressClassName: nginx -------------------------------------------------------------------------------- /pt/day-11/README.md: -------------------------------------------------------------------------------- 1 | # Descomplicando o Kubernetes 2 | ## DAY-11 3 | 4 |   5 | 6 | ## Conteúdo do Day-11 7 | 8 | - [Descomplicando o Kubernetes](#descomplicando-o-kubernetes) 9 | - [DAY-11](#day-11) 10 | - [Conteúdo do Day-11](#conteúdo-do-day-11) 11 | - [Início da aula do Day-11](#início-da-aula-do-day-11) 12 | - [O que iremos ver hoje?](#o-que-iremos-ver-hoje) 13 | - [Introdução ao Horizontal Pod Autoscaler (HPA)](#introdução-ao-horizontal-pod-autoscaler-hpa) 14 | - [Como o HPA Funciona?](#como-o-hpa-funciona) 15 | - [Introdução ao Metrics Server](#introdução-ao-metrics-server) 16 | - [Por que o Metrics Server é importante para o HPA?](#por-que-o-metrics-server-é-importante-para-o-hpa) 17 | - [Instalando o Metrics Server](#instalando-o-metrics-server) 18 | - [No Amazon EKS e na maioria dos clusters Kubernetes](#no-amazon-eks-e-na-maioria-dos-clusters-kubernetes) 19 | - [No Minikube:](#no-minikube) 20 | - [No KinD (Kubernetes in Docker):](#no-kind-kubernetes-in-docker) 21 | - [Verificando a Instalação do Metrics Server](#verificando-a-instalação-do-metrics-server) 22 | - [Obtendo Métricas](#obtendo-métricas) 23 | - [Criando um HPA](#criando-um-hpa) 24 | - [Exemplos Práticos com HPA](#exemplos-práticos-com-hpa) 25 | - [Autoscaling com base na utilização de CPU](#autoscaling-com-base-na-utilização-de-cpu) 26 | - [Autoscaling com base na utilização de Memória](#autoscaling-com-base-na-utilização-de-memória) 27 | - [Configuração Avançada de HPA: Definindo Comportamento de Escalonamento](#configuração-avançada-de-hpa-definindo-comportamento-de-escalonamento) 28 | - [ContainerResource](#containerresource) 29 | - [Detalhes do Algoritmo de Escalonamento](#detalhes-do-algoritmo-de-escalonamento) 30 | - [Configurações Avançadas e Uso Prático](#configurações-avançadas-e-uso-prático) 31 | - [Integrando HPA com Prometheus para Métricas Customizadas](#integrando-hpa-com-prometheus-para-métricas-customizadas) 32 | - [A sua lição de casa](#a-sua-lição-de-casa) 33 | - [Final do Day-11](#final-do-day-11) 34 | 35 |   36 | 37 | ### Início da aula do Day-11 38 | 39 | #### O que iremos ver hoje? 40 | 41 | Hoje é um dia particularmente fascinante! Vamos desbravar os territórios do Kubernetes, explorando a magia do Horizontal Pod Autoscaler (HPA), uma ferramenta indispensável para quem almeja uma operação eficiente e resiliente. Portanto, afivelem os cintos e preparem-se para uma jornada de descobertas. A aventura #VAIIII começar! 42 | 43 | #### Introdução ao Horizontal Pod Autoscaler (HPA) 44 | 45 | O Horizontal Pod Autoscaler, carinhosamente conhecido como HPA, é uma das joias brilhantes incrustadas no coração do Kubernetes. Com o HPA, podemos ajustar automaticamente o número de réplicas de um conjunto de pods, assegurando que nosso aplicativo tenha sempre os recursos necessários para performar eficientemente, sem desperdiçar recursos. O HPA é como um maestro que, com a batuta das métricas, rege a orquestra de pods, assegurando que a harmonia seja mantida mesmo quando a sinfonia do tráfego de rede atinge seu crescendo. 46 | 47 | #### Como o HPA Funciona? 48 | 49 | O HPA é o olheiro vigilante que monitora as métricas dos nossos pods. A cada batida do seu coração métrico, que ocorre em intervalos regulares, ele avalia se os pods estão suando a camisa para atender às demandas ou se estão relaxando mais do que deveriam. Com base nessa avaliação, ele toma a decisão sábia de convocar mais soldados para o campo de batalha ou de dispensar alguns para um merecido descanso. 50 | 51 | Certamente! O Metrics Server é uma componente crucial para o funcionamento do Horizontal Pod Autoscaler (HPA), pois fornece as métricas necessárias para que o HPA tome decisões de escalonamento. Vamos entender um pouco mais sobre o Metrics Server e como instalá-lo em diferentes ambientes Kubernetes, incluindo Minikube e KinD. 52 | 53 | --- 54 | 55 | ## Introdução ao Metrics Server 56 | 57 | Antes de começarmos a explorar o Horizontal Pod Autoscaler (HPA), é essencial termos o Metrics Server instalado em nosso cluster Kubernetes. O Metrics Server é um agregador de métricas de recursos de sistema, que coleta métricas como uso de CPU e memória dos nós e pods no cluster. Essas métricas são vitais para o funcionamento do HPA, pois são usadas para determinar quando e como escalar os recursos. 58 | 59 | ### Por que o Metrics Server é importante para o HPA? 60 | 61 | O HPA utiliza métricas de uso de recursos para tomar decisões inteligentes sobre o escalonamento dos pods. Por exemplo, se a utilização da CPU de um pod exceder um determinado limite, o HPA pode decidir aumentar o número de réplicas desse pod. Da mesma forma, se a utilização da CPU for muito baixa, o HPA pode decidir reduzir o número de réplicas. Para fazer isso de forma eficaz, o HPA precisa ter acesso a métricas precisas e atualizadas, que são fornecidas pelo Metrics Server. 62 | Portanto, precisamos antes conhecer essa peça fundamental para o dia de hoje! :D 63 | 64 | ### Instalando o Metrics Server 65 | 66 | #### No Amazon EKS e na maioria dos clusters Kubernetes 67 | 68 | Durante a nossa aula, estou com um cluster EKS, e para instalar o Metrics Server, podemos usar o seguinte comando: 69 | 70 | ```bash 71 | kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml 72 | ``` 73 | 74 | Esse comando aplica o manifesto do Metrics Server ao seu cluster, instalando todos os componentes necessários. 75 | 76 | #### No Minikube: 77 | 78 | A instalação do Metrics Server no Minikube é bastante direta. Use o seguinte comando para habilitar o Metrics Server: 79 | 80 | ```bash 81 | minikube addons enable metrics-server 82 | ``` 83 | 84 | Após a execução deste comando, o Metrics Server será instalado e ativado em seu cluster Minikube. 85 | 86 | #### No KinD (Kubernetes in Docker): 87 | 88 | Para o KinD, você pode usar o mesmo comando que usou para o EKS: 89 | 90 | ```bash 91 | kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml 92 | ``` 93 | 94 | #### Verificando a Instalação do Metrics Server 95 | 96 | Após a instalação do Metrics Server, é uma boa prática verificar se ele foi instalado corretamente e está funcionando como esperado. Execute o seguinte comando para obter a lista de pods no namespace `kube-system` e verificar se o pod do Metrics Server está em execução: 97 | 98 | ```bash 99 | kubectl get pods -n kube-system | grep metrics-server 100 | ``` 101 | 102 | #### Obtendo Métricas 103 | 104 | Com o Metrics Server em execução, agora você pode começar a coletar métricas de seu cluster. Aqui está um exemplo de como você pode obter métricas de uso de CPU e memória para todos os seus nodes: 105 | 106 | ```bash 107 | kubectl top nodes 108 | ``` 109 | 110 | E para obter métricas de uso de CPU e memória para todos os seus pods: 111 | 112 | ```bash 113 | kubectl top pods 114 | ``` 115 | 116 | Esses comandos fornecem uma visão rápida da utilização de recursos em seu cluster, o que é crucial para entender e otimizar o desempenho de seus aplicativos. 117 | 118 | ### Criando um HPA 119 | 120 | Antes de nos aprofundarmos no HPA, vamos recapitular criando um deployment simples para o nosso confiável servidor Nginx. 121 | 122 | ```yaml 123 | # Definição de um Deployment para o servidor Nginx 124 | apiVersion: apps/v1 # Versão da API que define um Deployment 125 | kind: Deployment # Tipo de recurso que estamos definindo 126 | metadata: 127 | name: nginx-deployment # Nome do nosso Deployment 128 | spec: 129 | replicas: 3 # Número inicial de réplicas 130 | selector: 131 | matchLabels: 132 | app: nginx # Label que identifica os pods deste Deployment 133 | template: 134 | metadata: 135 | labels: 136 | app: nginx # Label aplicada aos pods 137 | spec: 138 | containers: 139 | - name: nginx # Nome do contêiner 140 | image: nginx:latest # Imagem do contêiner 141 | ports: 142 | - containerPort: 80 # Porta exposta pelo contêiner 143 | resources: 144 | limits: 145 | cpu: 500m # Limite de CPU 146 | memory: 256Mi # Limite de memória 147 | requests: 148 | cpu: 250m # Requisição de CPU 149 | memory: 128Mi # Requisição de memória 150 | ``` 151 | 152 | Agora, com nosso deployment pronto, vamos dar o próximo passo na criação do nosso HPA. 153 | 154 | ```yaml 155 | # Definição do HPA para o nginx-deployment 156 | apiVersion: autoscaling/v2 # Versão da API que define um HPA 157 | kind: HorizontalPodAutoscaler # Tipo de recurso que estamos definindo 158 | metadata: 159 | name: nginx-deployment-hpa # Nome do nosso HPA 160 | spec: 161 | scaleTargetRef: 162 | apiVersion: apps/v1 # A versão da API do recurso alvo 163 | kind: Deployment # O tipo de recurso alvo 164 | name: nginx-deployment # O nome do recurso alvo 165 | minReplicas: 3 # Número mínimo de réplicas 166 | maxReplicas: 10 # Número máximo de réplicas 167 | metrics: 168 | - type: Resource # Tipo de métrica (recurso do sistema) 169 | resource: 170 | name: cpu # Nome da métrica (CPU neste caso) 171 | target: 172 | type: Utilization # Tipo de alvo (utilização) 173 | averageUtilization: 50 # Valor alvo (50% de utilização) 174 | ``` 175 | 176 | Neste exemplo, criamos um HPA que monitora a utilização da CPU do nosso `nginx-deployment`. O HPA se esforçará para manter a utilização da CPU em torno de 50%, ajustando o número de réplicas entre 3 e 10 conforme necessário. 177 | 178 | Para aplicar esta configuração ao seu cluster Kubernetes, salve o conteúdo acima em um arquivo chamado 179 | 180 | `nginx-deployment-hpa.yaml` e execute o seguinte comando: 181 | 182 | ```bash 183 | kubectl apply -f nginx-deployment-hpa.yaml 184 | ``` 185 | 186 | Agora, você tem um HPA monitorando e ajustando a escala do seu `nginx-deployment` baseado na utilização da CPU. Fantástico, não é? 187 | 188 | ### Exemplos Práticos com HPA 189 | 190 | Agora que você já entende o básico sobre o HPA, é hora de rolar as mangas e entrar na prática. Vamos explorar como o HPA responde a diferentes métricas e cenários. 191 | 192 | #### Autoscaling com base na utilização de CPU 193 | 194 | Vamos começar com um exemplo clássico de escalonamento baseado na utilização da CPU, que já discutimos anteriormente. Para tornar a aprendizagem mais interativa, vamos simular um aumento de tráfego e observar como o HPA responde a essa mudança. 195 | 196 | ```bash 197 | kubectl run -i --tty load-generator --image=busybox /bin/sh 198 | 199 | while true; do wget -q -O- http://nginx-deployment.default.svc.cluster.local; done 200 | ``` 201 | 202 | Este script simples cria uma carga constante no nosso deployment, fazendo requisições contínuas ao servidor Nginx. Você poderá observar como o HPA ajusta o número de réplicas para manter a utilização da CPU em torno do limite definido. 203 | 204 | #### Autoscaling com base na utilização de Memória 205 | 206 | O HPA não é apenas um mestre em lidar com a CPU, ele também tem um olho afiado para a memória. Vamos explorar como configurar o HPA para escalar baseado na utilização de memória. 207 | 208 | ```yaml 209 | # Definição do HPA para escalonamento baseado em memória 210 | apiVersion: autoscaling/v2 # Versão da API que define um HPA 211 | kind: HorizontalPodAutoscaler # Tipo de recurso que estamos definindo 212 | metadata: 213 | name: nginx-deployment-hpa-memory # Nome do nosso HPA 214 | spec: 215 | scaleTargetRef: 216 | apiVersion: apps/v1 # A versão da API do recurso alvo 217 | kind: Deployment # O tipo de recurso alvo 218 | name: nginx-deployment # O nome do recurso alvo 219 | minReplicas: 3 # Número mínimo de réplicas 220 | maxReplicas: 10 # Número máximo de réplicas 221 | metrics: 222 | - type: Resource # Tipo de métrica (recurso do sistema) 223 | resource: 224 | name: memory # Nome da métrica (memória neste caso) 225 | target: 226 | type: Utilization # Tipo de alvo (utilização) 227 | averageUtilization: 70 # Valor alvo (70% de utilização) 228 | ``` 229 | 230 | Neste exemplo, o HPA vai ajustar o número de réplicas para manter a utilização de memória em cerca de 70%. Assim, nosso deployment pode respirar livremente mesmo quando a demanda aumenta. 231 | 232 | #### Configuração Avançada de HPA: Definindo Comportamento de Escalonamento 233 | 234 | O HPA é flexível e permite que você defina como ele deve se comportar durante o escalonamento para cima e para baixo. Vamos explorar um exemplo: 235 | 236 | ```yaml 237 | # Definição de HPA com configurações avançadas de comportamento 238 | apiVersion: autoscaling/v2 # Versão da API que define um HPA 239 | kind: HorizontalPodAutoscaler # Tipo de recurso que estamos definindo 240 | metadata: 241 | name: nginx-deployment-hpa # Nome do nosso HPA 242 | spec: 243 | scaleTargetRef: 244 | apiVersion: apps/v1 # A versão da API do recurso alvo 245 | kind: Deployment # O tipo de recurso alvo 246 | name: nginx-deployment # O nome do recurso alvo 247 | minReplicas: 3 # Número mínimo de réplicas 248 | maxReplicas: 10 # Número máximo de réplicas 249 | metrics: 250 | - type: Resource # Tipo de métrica (recurso do sistema) 251 | resource: 252 | name: cpu # Nome da métrica (CPU neste caso) 253 | target: 254 | type: Utilization # Tipo de alvo (utilização) 255 | averageUtilization: 50 # Valor alvo (50% de utilização) 256 | behavior: 257 | scaleUp: 258 | stabilizationWindowSeconds: 0 # Período de estabilização para escalonamento para cima 259 | policies: 260 | - type: Percent # Tipo de política (percentual) 261 | value: 100 # Valor da política (100%) 262 | periodSeconds: 15 # Período da política (15 segundos) 263 | scaleDown: 264 | stabilizationWindowSeconds: 300 # Período de estabilização para escalonamento para baixo 265 | policies: 266 | - type: Percent # Tipo de política (percentual) 267 | value: 100 # Valor da política (100%) 268 | periodSeconds: 15 # Período da política (15 segundos) 269 | ``` 270 | 271 | Neste exemplo, especificamos um comportamento de escalonamento onde o HPA pode escalar para cima imediatamente, mas vai esperar por 5 minutos (300 segundos) após o último escalonamento para cima antes de considerar um escalonamento para baixo. Isso ajuda a evitar flutuações rápidas na contagem de réplicas, proporcionando um ambiente mais estável para nossos pods. 272 | 273 | 274 | #### ContainerResource 275 | 276 | O tipo de métrica `ContainerResource` no Kubernetes permite que você especifique métricas de recursos específicas do container para escalar. Diferente das métricas de recurso comuns que são aplicadas a todos os contêineres em um Pod, as métricas `ContainerResource` permitem especificar métricas para um contêiner específico dentro de um Pod. Isso pode ser útil em cenários onde você tem múltiplos contêineres em um Pod, mas quer escalar com base na utilização de recursos de um contêiner específico. 277 | 278 | Aqui está um exemplo de como você pode configurar um Horizontal Pod Autoscaler (HPA) usando uma métrica `ContainerResource` para escalar um Deployment com base na utilização de CPU de um contêiner específico: 279 | 280 | ```yaml 281 | apiVersion: autoscaling/v2beta2 282 | kind: HorizontalPodAutoscaler 283 | metadata: 284 | name: nginx-hpa 285 | spec: 286 | scaleTargetRef: 287 | apiVersion: apps/v1 288 | kind: Deployment 289 | name: nginx 290 | minReplicas: 3 291 | maxReplicas: 10 292 | metrics: 293 | - type: ContainerResource 294 | containerResource: 295 | name: cpu 296 | container: nginx-NOME-COMPLETO-DO-CONTAINER 297 | target: 298 | type: Utilization 299 | averageUtilization: 50 300 | ``` 301 | 302 | No exemplo acima: 303 | 304 | - O tipo de métrica é definido como `ContainerResource`. 305 | - Dentro do bloco `containerResource`, especificamos o nome da métrica (`cpu`), o nome do contêiner (`my-container`) e o alvo de utilização (`averageUtilization: 50`). 306 | 307 | Isso significa que o HPA vai ajustar o número de réplicas do Deployment `my-app` para manter a utilização média de CPU do contêiner `nginx-NOME-COMPLETO-DO-CONTAINER` em torno de 50%. 308 | 309 | Este tipo de configuração permite um controle mais granular sobre o comportamento de autoscaling, especialmente em ambientes onde os Pods contêm múltiplos contêineres com diferentes perfis de utilização de recursos. 310 | 311 | 312 | #### Detalhes do Algoritmo de Escalonamento 313 | 314 | **Cálculo do Número de Réplicas** 315 | O núcleo do Horizontal Pod Autoscaler (HPA) é o seu algoritmo de escalonamento, que determina o número ideal de réplicas com base nas métricas fornecidas. A fórmula básica utilizada pelo HPA para calcular o número desejado de réplicas é: 316 | 317 | \[ \text{desiredReplicas} = \lceil \text{currentReplicas} \times \left( \frac{\text{currentMetricValue}}{\text{desiredMetricValue}} \right) \rceil \] 318 | 319 | **Exemplos com Valores Específicos:** 320 | 1. **Exemplo de Escala para Cima:** 321 | - Réplicas atuais: 2 322 | - Valor atual da métrica (CPU): 80% 323 | - Valor desejado da métrica (CPU): 50% 324 | - Cálculo: \(\lceil 2 \times (80\% / 50\%) \rceil = \lceil 3.2 \rceil = 4\) réplicas 325 | 326 | 2. **Exemplo de Escala para Baixo:** 327 | - Réplicas atuais: 5 328 | - Valor atual da métrica (CPU): 30% 329 | - Valor desejado da métrica (CPU): 50% 330 | - Cálculo: \(\lceil 5 \times (30\% / 50\%) \rceil = \lceil 3 \rceil = 3\) réplicas 331 | 332 | **Considerações Sobre Métricas e Estado dos Pods:** 333 | - **Métricas de Recurso por Pod e Personalizadas:** O HPA pode ser configurado para usar métricas padrão (como CPU e memória) ou métricas personalizadas definidas pelo usuário, permitindo maior flexibilidade. 334 | - **Tratamento de Pods sem Métricas ou Não Prontos:** Se um Pod não tiver métricas disponíveis ou não estiver pronto, ele pode ser excluído do cálculo de média, evitando decisões de escalonamento baseadas em dados incompletos. 335 | 336 | #### Configurações Avançadas e Uso Prático 337 | 338 | **Configurando Métricas Personalizadas e Múltiplas Métricas:** 339 | O HPA não se limita apenas a métricas de CPU e memória; ele pode ser configurado para usar uma variedade de métricas personalizadas. 340 | 341 | **Uso de Métricas Personalizadas: Exemplos e Dicas:** 342 | - **Exemplo:** Suponha que você tenha um serviço que deve escalar com base no número de solicitações HTTP por segundo. Você pode configurar o HPA para escalar com base nessa métrica personalizada. 343 | - **Dicas:** Ao usar métricas personalizadas, assegure-se de que as métricas sejam um indicador confiável da carga de trabalho e que o serviço de métricas esteja corretamente configurado e acessível pelo HPA. 344 | 345 | **Escalonamento com Base em Várias Métricas:** 346 | - O HPA pode ser configurado para levar em conta várias métricas ao mesmo tempo, permitindo um controle mais refinado do escalonamento. 347 | - Por exemplo, você pode configurar o HPA para escalar com base tanto na utilização de CPU quanto na memória, ou qualquer combinação de métricas padrão e personalizadas. 348 | 349 | 350 | #### Integrando HPA com Prometheus para Métricas Customizadas 351 | 352 | Para levar o autoscaling para o próximo nível, podemos integrar o HPA com o Prometheus. Com essa integração, podemos usar métricas do Prometheus para informar nossas decisões de autoscaling. 353 | 354 | A integração geralmente envolve a configuração de um adaptador de métricas personalizadas, como o `k8s-prometheus-adapter`. Uma vez configurado, o HPA pode acessar métricas do Prometheus e usá-las para tomar decisões de autoscaling. A documentação completa sobre como integrar o HPA com o Prometheus pode ser encontrada [aqui](#adicionar-link). 355 | 356 | ### A sua lição de casa 357 | 358 | Agora que você foi equipado com o conhecimento sobre o HPA, é hora de colocar esse conhecimento em prática. Configure um HPA em seu ambiente e experimente com diferentes métricas: CPU, memória e métricas personalizadas. Documente suas observações e compreenda como o HPA responde a diferentes cargas e situações. 359 | 360 | ### Final do Day-11 361 | 362 | E assim, chegamos ao fim do Day-11, uma jornada repleta de aprendizado e exploração. Hoje, você descobriu o poder do Horizontal Pod Autoscaler e como ele pode ajudar a manter seu aplicativo performando de maneira eficiente, mesmo sob diferentes condições de carga. Você não apenas aprendeu como ele funciona, mas também colocou a mão na massa com exemplos práticos. Continue praticando e explorando, e nos vemos no próximo dia da nossa aventura pelo Kubernetes! #VAIIII -------------------------------------------------------------------------------- /pt/day-13/README.md: -------------------------------------------------------------------------------- 1 | # Descomplicando o Kubernetes 2 | ## DAY-13: Descomplicando Kyverno e as Policies no Kubernetes 3 | 4 | ## Conteúdo do Day-13 5 | 6 | - [Descomplicando o Kubernetes](#descomplicando-o-kubernetes) 7 | - [DAY-13: Descomplicando Kyverno e as Policies no Kubernetes](#day-13-descomplicando-kyverno-e-as-policies-no-kubernetes) 8 | - [Conteúdo do Day-13](#conteúdo-do-day-13) 9 | - [O que iremos ver hoje?](#o-que-iremos-ver-hoje) 10 | - [Inicio do Day-13](#inicio-do-day-13) 11 | - [Introdução ao Kyverno](#introdução-ao-kyverno) 12 | - [Instalando o Kyverno](#instalando-o-kyverno) 13 | - [Utilizando Helm](#utilizando-helm) 14 | - [Verificando a Instalação](#verificando-a-instalação) 15 | - [Criando a nossa primeira Policy](#criando-a-nossa-primeira-policy) 16 | - [Mais exemplos de Policies](#mais-exemplos-de-policies) 17 | - [Exemplo de Política: Adicionar Label ao Namespace](#exemplo-de-política-adicionar-label-ao-namespace) 18 | - [Detalhes da Política](#detalhes-da-política) 19 | - [Arquivo de Política: `add-label-namespace.yaml`](#arquivo-de-política-add-label-namespaceyaml) 20 | - [Utilização da Política](#utilização-da-política) 21 | - [Exemplo de Política: Proibir Usuário Root](#exemplo-de-política-proibir-usuário-root) 22 | - [Detalhes da Política](#detalhes-da-política-1) 23 | - [Arquivo de Política: `disallow-root-user.yaml`](#arquivo-de-política-disallow-root-useryaml) 24 | - [Implementação e Efeito](#implementação-e-efeito) 25 | - [Exemplo de Política: Gerar ConfigMap para Namespace](#exemplo-de-política-gerar-configmap-para-namespace) 26 | - [Detalhes da Política](#detalhes-da-política-2) 27 | - [Arquivo de Política: `generate-configmap-for-namespace.yaml`](#arquivo-de-política-generate-configmap-for-namespaceyaml) 28 | - [Implementação e Utilidade](#implementação-e-utilidade) 29 | - [Exemplo de Política: Permitir Apenas Repositórios Confiáveis](#exemplo-de-política-permitir-apenas-repositórios-confiáveis) 30 | - [Detalhes da Política](#detalhes-da-política-3) 31 | - [Arquivo de Política: `registry-allowed.yaml`](#arquivo-de-política-registry-allowedyaml) 32 | - [Implementação e Impacto](#implementação-e-impacto) 33 | - [Exemplo de Política: Require Probes](#exemplo-de-política-require-probes) 34 | - [Detalhes da Política](#detalhes-da-política-4) 35 | - [Arquivo de Política: `require-probes.yaml`](#arquivo-de-política-require-probesyaml) 36 | - [Implementação e Impacto](#implementação-e-impacto-1) 37 | - [Exemplo de Política: Usando o Exclude](#exemplo-de-política-usando-o-exclude) 38 | - [Detalhes da Política](#detalhes-da-política-5) 39 | - [Arquivo de Política](#arquivo-de-política) 40 | - [Implementação e Efeitos](#implementação-e-efeitos) 41 | - [Final do Day-13](#final-do-day-13) 42 | - [Pontos-Chave Aprendidos](#pontos-chave-aprendidos) 43 | 44 | ## O que iremos ver hoje? 45 | 46 | Hoje, exploraremos as funcionalidades e aplicações do Kyverno, uma ferramenta de gerenciamento de políticas essencial para a segurança e eficiência de clusters Kubernetes. Com uma abordagem detalhada e prática, você aprenderá a usar o Kyverno para automatizar tarefas cruciais, garantir a conformidade com normas e regras estabelecidas e melhorar a administração geral de seus ambientes Kubernetes. 47 | 48 | **Principais Tópicos Abordados:** 49 | 50 | 1. **Introdução ao Kyverno:** Uma visão geral do Kyverno, destacando sua importância e as principais funções de validação, mutação e geração de recursos. 51 | 52 | 2. **Instalação e Configuração:** Passo a passo para a instalação do Kyverno, incluindo métodos usando o Helm e arquivos YAML, e como verificar se a instalação foi bem-sucedida. 53 | 54 | 3. **Desenvolvendo Políticas Eficientes:** Aprenda a criar políticas para diferentes cenários, desde garantir limites de CPU e memória em Pods até aplicar automaticamente labels a namespaces e restringir a execução de containers como root. 55 | 56 | 4. **Exemplos Práticos:** Vários exemplos de políticas, ilustrando como o Kyverno pode ser aplicado para resolver problemas reais e melhorar a segurança e conformidade dos clusters Kubernetes. 57 | 58 | 5. **Dicas de Uso e Melhores Práticas:** Orientações sobre como aproveitar ao máximo o Kyverno, incluindo dicas de segurança, eficiência e automatização de processos. 59 | 60 | Ao final deste e-book, você terá uma compreensão abrangente do Kyverno e estará equipado com o conhecimento e as habilidades para implementá-lo efetivamente em seus próprios clusters Kubernetes. Este e-book é projetado tanto para iniciantes quanto para profissionais experientes, proporcionando informações valiosas e práticas para todos os níveis de expertise. 61 | 62 | 63 | ## Inicio do Day-13 64 | 65 | ### Introdução ao Kyverno 66 | 67 | Kyverno é uma ferramenta de gerenciamento de políticas para Kubernetes, focada na automação de várias tarefas relacionadas à segurança e configuração dos clusters de Kubernetes. Ele permite que você defina, gerencie e aplique políticas de forma declarativa para garantir que os clusters e suas cargas de trabalho estejam em conformidade com as regras e normas definidas. 68 | 69 | **Principais Funções do Kyverno:** 70 | 71 | 1. **Validação de Recursos:** Verifica se os recursos do Kubernetes estão em conformidade com as políticas definidas. Por exemplo, pode garantir que todos os Pods tenham limites de CPU e memória definidos. 72 | 73 | 2. **Mutação de Recursos:** Modifica automaticamente os recursos do Kubernetes para atender às políticas definidas. Por exemplo, pode adicionar automaticamente labels específicos a todos os novos Pods. 74 | 75 | 3. **Geração de Recursos:** Cria recursos adicionais do Kubernetes com base nas políticas definidas. Por exemplo, pode gerar NetworkPolicies para cada novo Namespace criado. 76 | 77 | 78 | ### Instalando o Kyverno 79 | 80 | A instalação do Kyverno em um cluster Kubernetes pode ser feita de várias maneiras, incluindo a utilização de um gerenciador de pacotes como o Helm, ou diretamente através de arquivos YAML. Aqui estão os passos básicos para instalar o Kyverno: 81 | 82 | #### Utilizando Helm 83 | 84 | O Helm é um gerenciador de pacotes para Kubernetes, que facilita a instalação e gerenciamento de aplicações. Para instalar o Kyverno com Helm, siga estes passos: 85 | 86 | 1. **Adicione o Repositório do Kyverno:** 87 | 88 | ```shell 89 | helm repo add kyverno https://kyverno.github.io/kyverno/ 90 | helm repo update 91 | ``` 92 | 93 | 2. **Instale o Kyverno:** 94 | 95 | Você pode instalar o Kyverno no namespace `kyverno` usando o seguinte comando: 96 | 97 | ```shell 98 | helm install kyverno kyverno/kyverno --namespace kyverno --create-namespace 99 | ``` 100 | 101 | ### Verificando a Instalação 102 | 103 | Após a instalação, é importante verificar se o Kyverno foi instalado corretamente e está funcionando como esperado. 104 | 105 | - **Verifique os Pods:** 106 | 107 | ```shell 108 | kubectl get pods -n kyverno 109 | ``` 110 | 111 | Este comando deve mostrar os pods do Kyverno em execução no namespace especificado. 112 | 113 | - **Verifique os CRDs:** 114 | 115 | ```shell 116 | kubectl get crd | grep kyverno 117 | ``` 118 | 119 | Este comando deve listar os CRDs relacionados ao Kyverno, indicando que foram criados corretamente. 120 | 121 | Lembrando que é sempre importante consultar a documentação oficial para obter as instruções mais atualizadas e detalhadas, especialmente se estiver trabalhando com uma configuração específica ou uma versão mais recente do Kyverno ou do Kubernetes. 122 | 123 | 124 | ### Criando a nossa primeira Policy 125 | 126 | Kyverno permite que você defina, gerencie e aplique políticas de forma declarativa para garantir que os clusters e suas cargas de trabalho estejam em conformidade com as regras e normas definidas. 127 | 128 | As políticas, ou as policies em inglês, do Kyverno podem ser aplicadas de duas maneiras principais: a nível de cluster (`ClusterPolicy`) ou a nível de namespace específico (`Policy`). 129 | 130 | 1. **ClusterPolicy**: Quando você define uma política como `ClusterPolicy`, ela é aplicada a todos os namespaces no cluster. Ou seja, as regras definidas em uma `ClusterPolicy` são automaticamente aplicadas a todos os recursos correspondentes em todos os namespaces, a menos que especificamente excluídos. 131 | 132 | 2. **Policy**: Se você deseja aplicar políticas a um namespace específico, você usaria o tipo `Policy`. As políticas definidas como `Policy` são aplicadas apenas dentro do namespace onde são criadas. 133 | 134 | Se você não especificar nenhum namespace na política ou usar `ClusterPolicy`, o Kyverno assumirá que a política deve ser aplicada globalmente, ou seja, em todos os namespaces. 135 | 136 | 137 | **Exemplo de Políticas do Kyverno:** 138 | 139 | 1. **Política de Limites de Recursos:** Garantir que todos os containers em um Pod tenham limites de CPU e memória definidos. Isso pode ser importante para evitar o uso excessivo de recursos em um cluster compartilhado. 140 | 141 | **Arquivo `require-resources-limits.yaml`:** 142 | ```yaml 143 | apiVersion: kyverno.io/v1 144 | kind: ClusterPolicy 145 | metadata: 146 | name: require-cpu-memory-limits 147 | spec: 148 | validationFailureAction: enforce 149 | rules: 150 | - name: validate-limits 151 | match: 152 | resources: 153 | kinds: 154 | - Pod 155 | validate: 156 | message: "CPU and memory limits are required" 157 | pattern: 158 | spec: 159 | containers: 160 | - name: "*" 161 | resources: 162 | limits: 163 | memory: "?*" 164 | cpu: "?*" 165 | ``` 166 | 167 | 168 | Depois do arquivo criado, agora bastar realizar o deploy em nosso cluster Kubernetes. 169 | 170 | ```bash 171 | kubectl apply -f require-resources-limits.yaml 172 | ``` 173 | 174 | Agora, tenta realizar o deploy de um simples Nginx sem definir o limite para os recursos. 175 | 176 | **Arquivo `pod.yaml`:** 177 | ```bash 178 | apiVersion: v1 179 | kind: Pod 180 | metadata: 181 | name: exemplo-pod 182 | spec: 183 | containers: 184 | - name: exemplo-container 185 | image: nginx 186 | ``` 187 | 188 | ```bash 189 | kubectl apply -f pod.yaml 190 | ``` 191 | 192 | ### Mais exemplos de Policies 193 | Continuando com a explicação e exemplos de políticas do Kyverno para gerenciamento de clusters Kubernetes: 194 | 195 | Entendi, vou formatar o texto para que esteja pronto para ser copiado para o Google Docs: 196 | 197 | 198 | #### Exemplo de Política: Adicionar Label ao Namespace 199 | 200 | A política `add-label-namespace` é projetada para automatizar a adição de um label específico a todos os Namespaces em um cluster Kubernetes. Esta abordagem é essencial para a organização, monitoramento e controle de acesso em ambientes complexos. 201 | 202 | ##### Detalhes da Política 203 | 204 | O label adicionado por esta política é `Jeferson: "Lindo_Demais"`. A aplicação deste label a todos os Namespaces facilita a identificação e a categorização dos mesmos, permitindo uma gestão mais eficiente e uma padronização no uso de labels. 205 | 206 | ##### Arquivo de Política: `add-label-namespace.yaml` 207 | 208 | ```yaml 209 | apiVersion: kyverno.io/v1 210 | kind: ClusterPolicy 211 | metadata: 212 | name: add-label-namespace 213 | spec: 214 | rules: 215 | - name: add-label-ns 216 | match: 217 | resources: 218 | kinds: 219 | - Namespace 220 | mutate: 221 | patchStrategicMerge: 222 | metadata: 223 | labels: 224 | Jeferson: "Lindo_Demais" 225 | ``` 226 | 227 | ##### Utilização da Política 228 | 229 | Esta política garante que cada Namespace no cluster seja automaticamente etiquetado com `Jeferson: "Lindo_Demais"`. Isso é particularmente útil para garantir a conformidade e a uniformidade na atribuição de labels, facilitando operações como filtragem e busca de Namespaces com base em critérios específicos. 230 | 231 | 232 | #### Exemplo de Política: Proibir Usuário Root 233 | 234 | A política `disallow-root-user` é uma regra de segurança crítica no gerenciamento de clusters Kubernetes. Ela proíbe a execução de containers como usuário root dentro de Pods. Este controle ajuda a prevenir possíveis vulnerabilidades de segurança e a reforçar as melhores práticas no ambiente de contêineres. 235 | 236 | ##### Detalhes da Política 237 | 238 | O principal objetivo desta política é garantir que nenhum Pod no cluster execute containers como o usuário root. A execução de containers como root pode expor o sistema a riscos de segurança, incluindo acessos não autorizados e potenciais danos ao sistema host. 239 | 240 | ##### Arquivo de Política: `disallow-root-user.yaml` 241 | 242 | ```yaml 243 | apiVersion: kyverno.io/v1 244 | kind: ClusterPolicy 245 | metadata: 246 | name: disallow-root-user 247 | spec: 248 | validationFailureAction: Enforce 249 | rules: 250 | - name: check-runAsNonRoot 251 | match: 252 | resources: 253 | kinds: 254 | - Pod 255 | validate: 256 | message: "Running as root is not allowed. Set runAsNonRoot to true." 257 | pattern: 258 | spec: 259 | containers: 260 | - securityContext: 261 | runAsNonRoot: true 262 | ``` 263 | 264 | ##### Implementação e Efeito 265 | 266 | Ao aplicar esta política, todos os Pods que tentarem executar containers como usuário root serão impedidos, com a exibição de uma mensagem de erro indicando que a execução como root não é permitida. Isso assegura uma camada adicional de segurança no ambiente Kubernetes, evitando práticas que possam comprometer a integridade e a segurança do cluster. 267 | 268 | 269 | #### Exemplo de Política: Gerar ConfigMap para Namespace 270 | 271 | A política `generate-configmap-for-namespace` é uma estratégia prática no gerenciamento de Kubernetes para automatizar a criação de ConfigMaps em Namespaces. Esta política simplifica a configuração e a gestão de múltiplos ambientes dentro de um cluster. 272 | 273 | ##### Detalhes da Política 274 | 275 | Esta política é projetada para criar automaticamente um ConfigMap em cada Namespace recém-criado. O ConfigMap gerado, denominado `default-configmap`, inclui um conjunto padrão de chaves e valores, facilitando a configuração inicial e a padronização dos Namespaces. 276 | 277 | ##### Arquivo de Política: `generate-configmap-for-namespace.yaml` 278 | 279 | ```yaml 280 | apiVersion: kyverno.io/v1 281 | kind: ClusterPolicy 282 | metadata: 283 | name: generate-configmap-for-namespace 284 | spec: 285 | rules: 286 | - name: generate-namespace-configmap 287 | match: 288 | resources: 289 | kinds: 290 | - Namespace 291 | generate: 292 | kind: ConfigMap 293 | name: default-configmap 294 | namespace: "{{request.object.metadata.name}}" 295 | data: 296 | data: 297 | key1: "value1" 298 | key2: "value2" 299 | ``` 300 | 301 | ##### Implementação e Utilidade 302 | 303 | A aplicação desta política resulta na criação automática de um ConfigMap padrão em cada Namespace novo, proporcionando uma forma rápida e eficiente de distribuir configurações comuns e informações essenciais. Isso é particularmente útil em cenários onde a consistência e a automatização de configurações são cruciais. 304 | 305 | 306 | #### Exemplo de Política: Permitir Apenas Repositórios Confiáveis 307 | 308 | A política `ensure-images-from-trusted-repo` é essencial para a segurança dos clusters Kubernetes, garantindo que todos os Pods utilizem imagens provenientes apenas de repositórios confiáveis. Esta política ajuda a prevenir a execução de imagens não verificadas ou potencialmente mal-intencionadas. 309 | 310 | ##### Detalhes da Política 311 | 312 | Esta política impõe que todas as imagens de containers usadas nos Pods devem ser originárias de repositórios especificados e confiáveis. A estratégia é crucial para manter a integridade e a segurança do ambiente de containers, evitando riscos associados a imagens desconhecidas ou não autorizadas. 313 | 314 | ##### Arquivo de Política: `registry-allowed.yaml` 315 | 316 | ```yaml 317 | apiVersion: kyverno.io/v1 318 | kind: ClusterPolicy 319 | metadata: 320 | name: ensure-images-from-trusted-repo 321 | spec: 322 | validationFailureAction: enforce 323 | rules: 324 | - name: trusted-repo-check 325 | match: 326 | resources: 327 | kinds: 328 | - Pod 329 | validate: 330 | message: "Only images from trusted repositories are allowed" 331 | pattern: 332 | spec: 333 | containers: 334 | - name: "*" 335 | image: "trustedrepo.com/*" 336 | ``` 337 | 338 | ##### Implementação e Impacto 339 | 340 | Com a implementação desta política, qualquer tentativa de implantar um Pod com uma imagem de um repositório não confiável será bloqueada. A política assegura que apenas imagens de fontes aprovadas sejam usadas, fortalecendo a segurança do cluster contra vulnerabilidades e ataques externos. 341 | 342 | 343 | ##### Exemplo de Política: Require Probes 344 | 345 | A política `require-readinessprobe` desempenha um papel crucial no gerenciamento de tráfego e na garantia da disponibilidade de serviços em um cluster Kubernetes. Ela exige que todos os Pods tenham uma sonda de prontidão (readiness probe) configurada, assegurando que o tráfego seja direcionado para os Pods apenas quando estiverem prontos para processar solicitações. 346 | 347 | ##### Detalhes da Política 348 | 349 | Esta política visa melhorar a confiabilidade e eficiência dos serviços executados no cluster, garantindo que os Pods estejam prontos para receber tráfego antes de serem expostos a solicitações externas. A sonda de prontidão verifica se o Pod está pronto para atender às solicitações, ajudando a evitar interrupções e problemas de desempenho. 350 | 351 | ##### Arquivo de Política: `require-probes.yaml` 352 | 353 | ```yaml 354 | apiVersion: kyverno.io/v1 355 | kind: ClusterPolicy 356 | metadata: 357 | name: require-readinessprobe 358 | spec: 359 | validationFailureAction: Enforce 360 | rules: 361 | - name: require-readinessProbe 362 | match: 363 | resources: 364 | kinds: 365 | - Pod 366 | validate: 367 | message: "Readiness probe is required." 368 | pattern: 369 | spec: 370 | containers: 371 | - readinessProbe: 372 | httpGet: 373 | path: "/" 374 | port: 8080 375 | ``` 376 | 377 | ##### Implementação e Impacto 378 | 379 | Com a aplicação desta política, todos os novos Pods ou Pods atualizados devem incluir uma configuração de sonda de prontidão, que normalmente envolve a especificação de um caminho e porta para checagem HTTP. Isso assegura que o serviço só receba tráfego quando estiver totalmente operacional, melhorando a confiabilidade e a experiência do usuário. 380 | 381 | 382 | #### Exemplo de Política: Usando o Exclude 383 | 384 | A política `require-resources-limits` é uma abordagem proativa para gerenciar a utilização de recursos em um cluster Kubernetes. Ela garante que todos os Pods tenham limites de recursos definidos, como CPU e memória, mas com uma exceção específica para um namespace. 385 | 386 | ##### Detalhes da Política 387 | 388 | Essa política impõe que cada Pod no cluster tenha limites explícitos de CPU e memória configurados. Isso é crucial para evitar o consumo excessivo de recursos, que pode afetar outros Pods e a estabilidade geral do cluster. No entanto, esta política exclui especificamente o namespace `giropops` desta regra. 389 | 390 | ##### Arquivo de Política 391 | 392 | ```yaml 393 | apiVersion: kyverno.io/v1 394 | kind: ClusterPolicy 395 | metadata: 396 | name: require-resources-limits 397 | spec: 398 | validationFailureAction: Enforce 399 | rules: 400 | - name: validate-limits 401 | match: 402 | resources: 403 | kinds: 404 | - Pod 405 | exclude: 406 | resources: 407 | namespaces: 408 | - giropops 409 | validate: 410 | message: "Precisa definir o limites de recursos" 411 | pattern: 412 | spec: 413 | containers: 414 | - name: "*" 415 | resources: 416 | limits: 417 | cpu: "?*" 418 | memory: "?*" 419 | ``` 420 | 421 | ##### Implementação e Efeitos 422 | 423 | Ao aplicar esta política, todos os Pods novos ou atualizados precisam ter limites de recursos claramente definidos, exceto aqueles no namespace `giropops`. Isso assegura uma melhor gestão de recursos e evita situações onde alguns Pods possam monopolizar recursos em detrimento de outros. 424 | 425 | 426 | ## Final do Day-13 427 | 428 | Ao longo deste artigo, exploramos as capacidades e funcionalidades do Kyverno, uma ferramenta inovadora e essencial para o gerenciamento de políticas em clusters Kubernetes. Compreendemos como o Kyverno simplifica e automatiza tarefas críticas relacionadas à segurança, conformidade e configuração, tornando-se um componente indispensável na administração de ambientes Kubernetes. 429 | 430 | #### Pontos-Chave Aprendidos 431 | 432 | 1. **Automação e Conformidade:** Vimos como o Kyverno permite definir, gerenciar e aplicar políticas de forma declarativa, garantindo que os recursos do Kubernetes estejam sempre em conformidade com as regras e normas estabelecidas. Esta abordagem reduz significativamente o esforço manual, minimiza erros e assegura uma maior consistência em todo o ambiente. 433 | 434 | 2. **Validação, Mutação e Geração de Recursos:** Aprendemos sobre as três funções principais do Kyverno – validação, mutação e geração de recursos – e como cada uma delas desempenha um papel vital na gestão eficaz do cluster. Estas funções proporcionam um controle granular sobre os recursos, desde a garantia de limites de CPU e memória até a aplicação automática de labels e a criação dinâmica de ConfigMaps. 435 | 436 | 3. **Flexibilidade de Políticas:** Discutimos a diferença entre `ClusterPolicy` e `Policy`, destacando como o Kyverno oferece flexibilidade para aplicar políticas em todo o cluster ou em namespaces específicos. Isso permite uma gestão personalizada e adaptada às necessidades de diferentes partes do cluster. 437 | 438 | 4. **Instalação e Verificação:** Abordamos as várias maneiras de instalar o Kyverno, com foco especial no uso do Helm, um gerenciador de pacotes popular para Kubernetes. Também exploramos como verificar a instalação correta do Kyverno, assegurando que tudo esteja funcionando conforme esperado. 439 | 440 | 5. **Práticas de Segurança:** O artigo enfatizou a importância da segurança em Kubernetes, demonstrada por políticas como a proibição de execução de containers como usuário root e a exigência de imagens provenientes de repositórios confiáveis. Essas políticas ajudam a prevenir vulnerabilidades e garantir a integridade do cluster. 441 | 442 | 6. **Automatização e Eficiência:** Por fim, aprendemos como o Kyverno facilita a automatização e a eficiência operacional. As políticas do Kyverno reduzem a necessidade de intervenção manual, aumentam a segurança e ajudam na conformidade regulatória, tornando a administração do Kubernetes mais simples e confiável. 443 | 444 | Em resumo, o Kyverno é uma ferramenta poderosa que transforma a maneira como as políticas são gerenciadas em Kubernetes. Seu enfoque na automação, flexibilidade e segurança o torna um componente essencial para qualquer administrador de Kubernetes que deseja otimizar a gestão de clusters, assegurar a conformidade e reforçar a segurança. Com o Kyverno, podemos atingir um nível mais alto de eficiência e confiança nos nossos ambientes Kubernetes, preparando-nos para enfrentar os desafios de um ecossistema em constante evolução. 445 | 446 | --- -------------------------------------------------------------------------------- /pt/day-14/images/image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/pt/day-14/images/image-1.png -------------------------------------------------------------------------------- /pt/day-14/images/image-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/pt/day-14/images/image-2.png -------------------------------------------------------------------------------- /pt/day-14/images/image-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/pt/day-14/images/image-3.png -------------------------------------------------------------------------------- /pt/day-16/files/README.md: -------------------------------------------------------------------------------- 1 | # charts-example 2 | -------------------------------------------------------------------------------- /pt/day-16/files/charts/giropops-senhas/.helmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/pt/day-16/files/charts/giropops-senhas/.helmignore -------------------------------------------------------------------------------- /pt/day-16/files/charts/giropops-senhas/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: giropops-senhas 3 | description: Esse é o chart do Giropops-Senhas, utilizados nos laboratórios de Kubernetes. 4 | version: 0.1.0 5 | appVersion: 0.1.0 6 | sources: 7 | - https://github.com/badtuxx/giropops-senhas 8 | -------------------------------------------------------------------------------- /pt/day-16/files/charts/giropops-senhas/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* Define a base para reutilização de labels */}} 2 | {{- define "app.labels" -}} 3 | app: {{ .labels.app | quote }} 4 | env: {{ .labels.env | quote }} 5 | live: {{ .labels.live | quote }} 6 | {{- end }} 7 | 8 | {{/* Template para especificações de recursos de containers */}} 9 | {{- define "app.resources" -}} 10 | requests: 11 | memory: {{ .resources.requests.memory }} 12 | cpu: {{ .resources.requests.cpu }} 13 | limits: 14 | memory: {{ .resources.limits.memory }} 15 | cpu: {{ .resources.limits.cpu }} 16 | {{- end }} 17 | 18 | {{/* Template para definição de portas em containers */}} 19 | {{- define "app.ports" -}} 20 | {{- range .ports }} 21 | - containerPort: {{ .port }} 22 | {{- end }} 23 | {{- end }} 24 | 25 | {{/* Template para gerar um ConfigMap para configurações de banco de dados */}} 26 | {{- define "database.configmap" -}} 27 | apiVersion: v1 28 | kind: ConfigMap 29 | metadata: 30 | name: {{ .component }}-db-config 31 | data: 32 | app-config.yaml: | 33 | {{- toYaml .config | nindent 4 }} 34 | {{- end }} 35 | 36 | {{/* Template para gerar um ConfigMap para configurações de observabilidade */}} 37 | {{- define "observability.configmap" -}} 38 | apiVersion: v1 39 | kind: ConfigMap 40 | metadata: 41 | name: {{ .component }}-observability-config 42 | data: 43 | app-config.json: | 44 | {{ toJson .config }} 45 | {{- end }} -------------------------------------------------------------------------------- /pt/day-16/files/charts/giropops-senhas/templates/configmap-db.yaml: -------------------------------------------------------------------------------- 1 | {{- range $component, $config := .Values.databases }} 2 | {{- $data := dict "component" $component "config" $config }} 3 | {{- include "database.configmap" $data | nindent 0 }} 4 | {{- end }} -------------------------------------------------------------------------------- /pt/day-16/files/charts/giropops-senhas/templates/configmap-observability.yaml: -------------------------------------------------------------------------------- 1 | {{- range $component, $config := .Values.observability }} 2 | {{- $data := dict "component" $component "config" $config }} 3 | {{- include "observability.configmap" $data | nindent 0 }} 4 | {{- end }} -------------------------------------------------------------------------------- /pt/day-16/files/charts/giropops-senhas/templates/deployments.yaml: -------------------------------------------------------------------------------- 1 | {{- range $component, $config := .Values.deployments }} 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: {{ $component }} 6 | labels: 7 | {{- include "app.labels" $config | nindent 4 }} 8 | spec: 9 | replicas: {{ $config.replicas | default 3 }} 10 | selector: 11 | matchLabels: 12 | app: {{ $config.labels.app }} 13 | template: 14 | metadata: 15 | labels: 16 | {{- include "app.labels" $config | nindent 8 }} 17 | spec: 18 | containers: 19 | - name: {{ $component }} 20 | image: {{ $config.image }} 21 | ports: 22 | {{- include "app.ports" $config | nindent 10 }} 23 | resources: 24 | {{- include "app.resources" $config | nindent 12 }} 25 | {{- if $config.env }} 26 | env: 27 | {{- range $config.env }} 28 | - name: {{ .name }} 29 | value: {{ .value }} 30 | {{- end }} 31 | {{- end }} 32 | --- 33 | {{- end }} -------------------------------------------------------------------------------- /pt/day-16/files/charts/giropops-senhas/templates/services.yaml: -------------------------------------------------------------------------------- 1 | {{- range $component, $config := .Values.services }} 2 | {{- range $port := $config.ports }} 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: {{ $component }}-{{ $port.name }} 7 | labels: 8 | {{- include "app.labels" $config | nindent 4 }} 9 | spec: 10 | type: {{ $port.serviceType }} 11 | ports: 12 | - port: {{ $port.port }} 13 | targetPort: {{ $port.targetPort }} 14 | protocol: TCP 15 | name: {{ $port.name }} 16 | {{- if eq $port.serviceType "NodePort" }} 17 | nodePort: {{ $port.nodePort }} 18 | {{- end }} 19 | selector: 20 | app: {{ $config.labels.app }} 21 | --- 22 | {{- end }} 23 | {{- end }} -------------------------------------------------------------------------------- /pt/day-16/files/charts/giropops-senhas/values.yaml: -------------------------------------------------------------------------------- 1 | deployments: 2 | giropops-senhas: 3 | name: "giropops-senhas" 4 | image: "linuxtips/giropops-senhas:1.0" 5 | replicas: 2 6 | labels: 7 | app: "giropops-senhas" 8 | env: "labs" 9 | live: "true" 10 | resources: 11 | requests: 12 | memory: "128Mi" 13 | cpu: "250m" 14 | limits: 15 | memory: "256Mi" 16 | cpu: "500m" 17 | redis: 18 | image: "redis" 19 | replicas: 1 20 | port: 6379 21 | labels: 22 | app: "redis" 23 | env: "labs" 24 | live: "true" 25 | resources: 26 | requests: 27 | memory: "128Mi" 28 | cpu: "250m" 29 | limits: 30 | memory: "256Mi" 31 | cpu: "500m" 32 | services: 33 | giropops-senhas: 34 | ports: 35 | - port: 5000 36 | targetPort: 5000 37 | name: "app" 38 | serviceType: NodePort 39 | NodePort: 32500 40 | - port: 8088 41 | targetPort: 8088 42 | name: "metrics" 43 | serviceType: ClusterIP 44 | labels: 45 | app: "giropops-senhas" 46 | env: "labs" 47 | live: "true" 48 | redis: 49 | ports: 50 | - port: 6379 51 | targetPort: 6379 52 | name: "service" 53 | serviceType: ClusterIP 54 | labels: 55 | app: "redis" 56 | env: "labs" 57 | live: "true" 58 | observability: 59 | giropops-senhas: 60 | logging: true 61 | metrics: 62 | enabled: true 63 | path: "/metrics" 64 | databases: 65 | giropops-senhas: 66 | type: "MySQL" 67 | host: "mysql.svc.cluster.local" 68 | port: 3306 69 | name: "MyDB" -------------------------------------------------------------------------------- /pt/day-16/images/github-pages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badtuxx/DescomplicandoKubernetes/68884d172a6c3e510005f3285b65107b7cc177e8/pt/day-16/images/github-pages.png -------------------------------------------------------------------------------- /pt/day-2/README.md: -------------------------------------------------------------------------------- 1 | # Descomplicando o Kubernetes 2 |   3 | ## DAY-2 - Descomplicando o Pod 4 |   5 | 6 | ### Conteúdo do Day-2 7 | 8 | - [Descomplicando o Kubernetes](#descomplicando-o-kubernetes) 9 | - [DAY-2](#day-2) 10 | - [Conteúdo do Day-3](#conteúdo-do-day-3) 11 | - [Inicio da aula do Day-2](#inicio-da-aula-do-day-2) 12 | - [O que iremos ver hoje?](#o-que-iremos-ver-hoje) 13 | - [O que é um Pod?](#o-que-é-um-pod) 14 | - [Criando um Pod](#criando-um-pod) 15 | - [Visualizando detalhes sobre os Pods](#visualizando-detalhes-sobre-os-pods) 16 | - [Removendo um Pod](#removendo-um-pod) 17 | - [Criando um Pod através de um arquivo YAML](#criando-um-pod-através-de-um-arquivo-yaml) 18 | - [Visualizando os logs do Pod](#visualizando-os-logs-do-pod) 19 | - [Criando um Pod com mais de um container](#criando-um-pod-com-mais-de-um-container) 20 | - [Os comandos `attach` e `exec`](#os-comandos-attach-e-exec) 21 | - [Criando um container com limites de memória e CPU](#criando-um-container-com-limites-de-memória-e-cpu) 22 | - [Adicionando um volume EmptyDir no Pod](#adicionando-um-volume-emptydir-no-pod) 23 | 24 | 25 | 26 |   27 | ### Inicio da aula do Day-2 28 |   29 | 30 | ### O que iremos ver hoje? 31 | 32 | Durante a aula de hoje, iremos ver todos os detalhes importantes sobre o menor objeto do Kubernetes, o Pod. 33 | Vamos ver desde a criação de um simples Pod, passando por Pod com multicontainers, com volumes e ainda com limitação ao consumo de recursos, como CPU ou memória. 34 | E claro, vamos aprender como ver todos os detalhes de um Pod em execução e brincar bastante com nossos arquivos YAML. 35 | 36 | ### O que é um Pod? 37 | 38 | 39 | Primeira coisa, o Pod é a menor unidade dentro de um cluster Kubernetes. 40 | 41 | Quando estamos falando sobre Pod, precisamos pensar que o Pod é uma caixinha que contém um ou mais containers. E esses containers compartilham os mesmos recursos do Pod, como por exemplo, o IP, o namespace, o volume, etc. 42 | 43 | Então, quando falamos de Pod, estamos falando de um ou mais containers que compartilham os mesmos recursos, ponto. 44 | 45 |   46 | 47 | #### Criando um Pod 48 | 49 | Temos basicamente duas formas de criar um Pod, a primeira é através de um comando no terminal e a segunda é através de um arquivo YAML. 50 | 51 | Vamos começar criando um Pod através de um comando no terminal. 52 | 53 | ```bash 54 | kubectl run giropops --image=nginx --port=80 55 | ``` 56 | 57 | O comando acima irá criar um Pod chamado giropops, com uma imagem do nginx e com a porta 80 exposta. 58 | 59 | 60 | #### Visualizando detalhes sobre os Pods 61 | 62 | Para ver o Pod criado, podemos usar o comando: 63 | 64 | ```bash 65 | kubectl get pods 66 | ``` 67 | 68 | O comando acima irá listar todos os Pods que estão em execução no cluster, na namespace default. 69 | 70 | Sim, temos namespaces no Kubernetes, mas isso é assunto para outro dia. Por enquanto, vamos focar em Pods e apenas temos que saber que por padrão, o Kubernetes irá criar todos os objetos dentro da namespace default se não especificarmos outra. 71 | 72 | Para ver os Pods em execução em todas as namespaces, podemos usar o comando: 73 | 74 | ```bash 75 | kubectl get pods --all-namespaces 76 | ``` 77 | 78 | Ou ainda, podemos usar o comando: 79 | 80 | ```bash 81 | kubectl get pods -A 82 | ``` 83 | 84 | Agora, se você quiser ver todos os Pods de uma namespace específica, você pode usar o comando: 85 | 86 | ```bash 87 | kubectl get pods -n 88 | ``` 89 | 90 | Por exemplo: 91 | 92 | ```bash 93 | kubectl get pods -n kube-system 94 | ``` 95 | 96 | O comando acima irá listar todos os Pods que estão em execução na namespace kube-system, que é a namespace onde o Kubernetes irá criar todos os objetos relacionados ao cluster, como por exemplo, os Pods do CoreDNS, do Kube-Proxy, do Kube-Controller-Manager, do Kube-Scheduler, etc. 97 | 98 | Caso você queira ver ainda mais detalhes sobre o Pod, você pode pedir para o Kubernetes mostrar os detalhes do Pod em formato YAML, usando o comando: 99 | 100 | ```bash 101 | kubectl get pods -o yaml 102 | ``` 103 | 104 | Por exemplo: 105 | 106 | ```bash 107 | kubectl get pods giropops -o yaml 108 | ``` 109 | 110 | O comando acima mostrará todos os detalhes do Pod em formato YAML, praticamente igual ao que você verá no arquivo YAML que utilizaremos a seguir para criar o Pod. Porém terá alguns detalhes a mais, como por exemplo, o UID do Pod, o nome do Node onde o Pod está sendo executado, etc. Afinal, esse Pod já está em execução, então o Kubernetes já tem mais detalhes sobre ele. 111 | 112 | Uma outra saída interessante é a saída em formato JSON, que você pode ver usando o comando: 113 | 114 | ```bash 115 | kubectl get pods -o json 116 | ``` 117 | 118 | Por exemplo: 119 | 120 | ```bash 121 | kubectl get pods giropops -o json 122 | ``` 123 | 124 | Ou seja, utilizando o parametro -o, você pode escolher o formato de saída que você quer ver, por exemplo, yaml, json, wide, etc. 125 | 126 | Ahh, a saída wide é interessante, pois ela mostra mais detalhes sobre o Pod, como por exemplo, o IP do Pod e o Node onde o Pod está sendo executado. 127 | 128 | ```bash 129 | kubectl get pods -o wide 130 | ``` 131 | 132 | Por exemplo: 133 | 134 | ```bash 135 | kubectl get pods giropops -o wide 136 | ``` 137 | 138 | Agora, se você quiser ver os detalhes do Pod, mas sem precisar usar o comando get, você pode usar o comando: 139 | 140 | ```bash 141 | kubectl describe pods 142 | ``` 143 | 144 | Por exemplo: 145 | 146 | ```bash 147 | kubectl describe pods giropops 148 | ``` 149 | 150 | Com o `describe` você pode ver todos os detalhes do Pod, inclusive os detalhes do container que está dentro do Pod. 151 | 152 | 153 | #### Removendo um Pod 154 | 155 | Agora vamos remover o Pod que criamos, usando o comando: 156 | 157 | ```bash 158 | kubectl delete pods giropops 159 | ``` 160 | 161 | Fácil né? Agora, vamos criar um Pod através de um arquivo YAML. 162 | 163 |   164 | 165 | #### Criando um Pod através de um arquivo YAML 166 | 167 | Vamos criar um arquivo YAML chamado pod.yaml com o seguinte conteúdo: 168 | 169 | ```yaml 170 | apiVersion: v1 # versão da API do Kubernetes 171 | kind: Pod # tipo do objeto que estamos criando 172 | metadata: # metadados do Pod 173 | name: giropops # nome do Pod que estamos criando 174 | labels: # labels do Pod 175 | run: giropops # label run com o valor giropops 176 | spec: # especificação do Pod 177 | containers: # containers que estão dentro do Pod 178 | - name: giropops # nome do container 179 | image: nginx # imagem do container 180 | ports: # portas que estão sendo expostas pelo container 181 | - containerPort: 80 # porta 80 exposta pelo container 182 | ``` 183 | 184 | Agora, vamos criar o Pod usando o arquivo YAML que acabamos de criar. 185 | 186 | ```bash 187 | kubectl apply -f pod.yaml 188 | ``` 189 | 190 | O comando acima irá criar o Pod usando o arquivo YAML que criamos. 191 | 192 | Para ver o Pod criado, podemos usar o comando: 193 | 194 | ```bash 195 | kubectl get pods 196 | ``` 197 | 198 | Já que usamos o comando `apply`, acho que vale a pena explicar o que ele faz. 199 | 200 | O comando `apply` é um comando que faz o que o nome diz, ele aplica o arquivo YAML no cluster, ou seja, ele cria o objeto que está descrito no arquivo YAML no cluster. Caso o objeto já exista, ele irá atualizá-lo com as informações que estão no arquivo YAML. 201 | 202 | Um outro comando que você pode usar para criar um objeto no cluster é o comando `create`, que também cria o objeto que está descrito no arquivo YAML no cluster, porém, caso o objeto já exista, ele irá retornar um erro. E por esse motivo que o comando `apply` é mais usado, pois ele atualiza o objeto caso ele já exista. :) 203 | 204 | Agora, vamos ver os detalhes do Pod que acabamos de criar. 205 | 206 | ```bash 207 | kubectl describe pods giropops 208 | ``` 209 | 210 | #### Visualizando os logs do Pod 211 | 212 | Outro comando muito útil para ver o que está acontecendo com o Pod, mais especificamente ver o que o container está logando, é o comando: 213 | 214 | ```bash 215 | kubectl logs giropops 216 | ``` 217 | 218 | Sendo que giropops é o nome do Pod que criamos. 219 | 220 | Se você quiser ver os logs do container em tempo real, você pode usar o comando: 221 | 222 | ```bash 223 | kubectl logs -f giropops 224 | ``` 225 | 226 | Simples né? Agora, vamos remover o Pod que criamos, usando o comando: 227 | 228 | ```bash 229 | kubectl delete pods giropops 230 | ``` 231 | 232 |   233 | 234 | #### Criando um Pod com mais de um container 235 | 236 | Vamos criar um arquivo YAML chamado pod-multi-container.yaml com o seguinte conteúdo: 237 | 238 | ```yaml 239 | apiVersion: v1 # versão da API do Kubernetes 240 | kind: Pod # tipo do objeto que estamos criando 241 | metadata: # metadados do Pod 242 | name: giropops # nome do Pod que estamos criando 243 | labels: # labels do Pod 244 | run: giropops # label run com o valor giropops 245 | spec: # especificação do Pod 246 | containers: # containers que estão dentro do Pod 247 | - name: girus # nome do container 248 | image: nginx # imagem do container 249 | ports: # portas que estão sendo expostas pelo container 250 | - containerPort: 80 # porta 80 exposta pelo container 251 | - name: strigus # nome do container 252 | image: alpine # imagem do container 253 | args: 254 | - sleep 255 | - "1800" 256 | ``` 257 | 258 | Com o manifesto acima, estamos criando um Pod com dois containers, um container chamado girus com a imagem nginx e outro container chamado strigus com a imagem alpine. Um coisa importante de lembrar é que o container do Alpine está sendo criado com o comando `sleep 1800` para que o container não pare de rodar, diferente do container do Nginx que possui um processo principal que fica sendo executado em primeiro plano, fazendo com que o container não pare de rodar. 259 | 260 | O Alpine é uma distribuição Linux que é muito leve, e não possui um processo principal que fica sendo executado em primeiro plano, por isso, precisamos executar o comando `sleep 1800` para que o container não pare de rodar, adicionando assim um processo principal que fica sendo executado em primeiro plano. 261 | 262 | Agora, vamos criar o Pod usando o arquivo YAML que acabamos de criar. 263 | 264 | ``` 265 | kubectl apply -f pod-multi-container.yaml 266 | ``` 267 | 268 | Para ver o Pod criado, podemos usar o comando: 269 | 270 | ```bash 271 | kubectl get pods 272 | ``` 273 | 274 | Agora, vamos ver os detalhes do Pod que acabamos de criar. 275 | 276 | ```bash 277 | kubectl describe pods giropops 278 | ``` 279 | 280 | ### Os comandos `attach` e `exec` 281 | 282 | Vamos conhecer dois novos comandos, o `attach` e o `exec`. 283 | 284 | O comando `attach` é usado para se conectar a um container que está rodando dentro de um Pod. Por exemplo, vamos se conectar ao container do Alpine que está rodando dentro do Pod que criamos. 285 | 286 | ```bash 287 | kubectl attach giropops -c strigus 288 | ``` 289 | 290 | Usando o `attach` é como se estivéssemos conectando diretamente em uma console de uma máquina virtual, não estamos criando nenhum processo dentro do container, apenas nos conectando a ele. 291 | 292 | Por esse motivo se tentarmos utilizar o `attach` para conectar no container que está rodando o Nginx, nós iremos conectar ao container e ficaremos presos ao processo do Nginx que está em execução em primeiro plano, e não conseguiremos executar nenhum outro comando. 293 | 294 | ```bash 295 | kubectl attach giropops -c girus 296 | ``` 297 | 298 | Para sair do container, basta apertar a tecla `Ctrl + C`. 299 | 300 | Entendeu? Só vamos usar o `attach` para se conectar a um container que está rodando dentro de um Pod, e não para executar comandos dentro do container. 301 | 302 | Agora, se você está afim de executar comandos dentro do container, você pode usar o comando `exec`. 303 | 304 | O comando `exec` é usado para executar comandos dentro de um container que está rodando dentro de um Pod. Por exemplo, vamos executar o comando `ls` dentro do container do Alpine que está rodando dentro do Pod que criamos. 305 | 306 | ```bash 307 | kubectl exec giropops -c strigus -- ls 308 | ``` 309 | 310 | Nós também podemos utilizar o `exec` para conectar em uma container que está rodando dentro de um Pod, porém, para isso, precisamos passar o parâmetro `-it` para o comando `exec`. 311 | 312 | ```bash 313 | kubectl exec giropops -c strigus -it -- sh 314 | ``` 315 | 316 | O parametro `-it` é usado para que o comando `exec` crie um processo dentro do container com interatividade e com um terminal, fazendo com que o comando `exec` se comporte como o comando `attach`, porém com a diferença que o comando `exec` cria um processo dentro do container, no caso o processo `sh`. E por esse motivo que o comando `exec` é mais usado, pois ele cria um processo dentro do container, diferente do comando `attach` que não cria nenhum processo dentro do container. 317 | 318 | Nesse caso, podemos até mesmo conectar no container do Nginx, pois ele vai conectar no container criando um processo que é o nosso interpretador de comandos `sh`, sendo possível executar qualquer comando dentro do container pois temos um shell para interagir com o container. 319 | 320 | ```bash 321 | kubectl exec giropops -c girus -it -- sh 322 | ``` 323 | 324 | Para sair do container, basta apertar a tecla `Ctrl + D`. 325 | 326 | Não esqueça de deletar o Pod que criamos. 327 | 328 | ```bash 329 | kubectl delete pods giropops 330 | ``` 331 | 332 |   333 | 334 | ### Criando um container com limites de memória e CPU 335 | 336 | Vamos criar um arquivo YAML chamado pod-limitado.yaml com o seguinte conteúdo: 337 | 338 | ```yaml 339 | apiVersion: v1 # versão da API do Kubernetes 340 | kind: Pod # tipo do objeto que estamos criando 341 | metadata: # metadados do Pod 342 | name: giropops # nome do Pod que estamos criando 343 | labels: # labels do Pod 344 | run: giropops # label run com o valor giropops 345 | spec: # especificação do Pod 346 | containers: # containers que estão dentro do Pod 347 | - name: girus # nome do container 348 | image: nginx # imagem do container 349 | ports: # portas que estão sendo expostas pelo container 350 | - containerPort: 80 # porta 80 exposta pelo container 351 | resources: # recursos que estão sendo utilizados pelo container 352 | limits: # limites máximo de recursos que o container pode utilizar 353 | memory: "128Mi" # limite de memória que está sendo utilizado pelo container, no caso 128 megabytes no máximo 354 | cpu: "0.5" # limite máxima de CPU que o container pode utilizar, no caso 50% de uma CPU no máximo 355 | requests: # recursos garantidos ao container 356 | memory: "64Mi" # memória garantida ao container, no caso 64 megabytes 357 | cpu: "0.3" # CPU garantida ao container, no caso 30% de uma CPU 358 | ``` 359 | 360 | Veja que estamos conhecendo alguns novos campos, o `resources`, o `limits` e o `requests`. 361 | 362 | O campo `resources` é usado para definir os recursos que serão utilizados pelo container, e dentro dele temos os campos `limits` e `requests`. 363 | 364 | O campo `limits` é usado para definir os limites máximos de recursos que o container pode utilizar, e o campo `requests` é usado para definir os recursos garantidos ao container. 365 | 366 | Simples demais! 367 | 368 | Os valores que passamos para os campos `limits` e `requests` foram: 369 | 370 | - `memory`: quantidade de memória que o container pode utilizar, por exemplo, `128Mi` ou `1Gi`. O valor `Mi` significa mebibytes e o valor `Gi` significa gibibytes. O valor `M` significa megabytes e o valor `G` significa gigabytes. O valor `Mi` é usado para definir o limite de memória em mebibytes, pois o Kubernetes utiliza o sistema de unidades binárias, e não o sistema de unidades decimais. O valor `M` é usado para definir o limite de memória em megabytes, pois o Docker utiliza o sistema de unidades decimais, e não o sistema de unidades binárias. Então, se você estiver utilizando o Docker, você pode usar o valor `M` para definir o limite de memória, mas se você estiver utilizando o Kubernetes, você deve usar o valor `Mi` para definir o limite de memória. 371 | 372 | - `cpu`: quantidade de CPU que o container pode utilizar, por exemplo, `0.5` ou `1`. O valor `0.5` significa 50% de uma CPU, e o valor `1` significa 100% de uma CPU. O valor `m` significa millicpu, ou seja, milicpu é igual a 1/1000 de uma CPU. Então, se você quiser definir o limite de CPU em 50% de uma CPU, você pode definir o valor `500m`, ou você pode definir o valor `0.5`, que é o mesmo que definir o valor `500m`. 373 | 374 | Agora vamos criar o Pod com os limites de memória e CPU. 375 | 376 | ```bash 377 | kubectl create -f pod-limitado.yaml 378 | ``` 379 | 380 | Agora vamos verificar se o Pod foi criado. 381 | 382 | ```bash 383 | kubectl get pods 384 | ``` 385 | 386 | Vamos verificar os detalhes do Pod. 387 | 388 | ```bash 389 | kubectl describe pod giropops 390 | ``` 391 | 392 | Veja que o Pod foi criado com sucesso, e que os limites de memória e CPU foram definidos conforme o arquivo YAML. 393 | 394 | Veja abaixo a parte da saída do comando `describe` que mostra os limites de memória e CPU. 395 | 396 | ```bash 397 | Containers: 398 | girus: 399 | Container ID: docker://e7b0c7b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 400 | Image: nginx 401 | Image ID: docker-pullable://nginx@sha256:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b 402 | Port: 80/TCP 403 | Host Port: 0/TCP 404 | State: Running 405 | Started: Wed, 01 Jan 2023 00:00:00 +0000 406 | Ready: True 407 | Restart Count: 0 408 | Limits: 409 | cpu: 500m 410 | memory: 128Mi 411 | Requests: 412 | cpu: 300m 413 | memory: 64Mi 414 | Environment: 415 | Mounts: 416 | /var/run/secrets/kubernetes.io/serviceaccount from default-token-0b0b0 (ro) 417 | ``` 418 | 419 | Veja que na saída acima, ele mostra o campo CPU com o valor `500m`, isso significa que o container pode utilizar no máximo 50% de uma CPU, afinal um CPU é igual a 1000 milliCPUs, e 50% de 1000 milicpus é 500 milliCPUs. 420 | 421 | Para você testar os limites de memória e CPU, você pode executar o comando `stress` dentro do container, que é um comando que faz o container consumir recursos de CPU e memória. Lembre-se de instalar o comando `stress`, pois ele não vem instalado por padrão. 422 | 423 | Para ficar fácil de testar, vamos criar um Pod com o Ubuntu com limitação de memória, e vamos instalar o comando `stress` dentro do container. 424 | 425 | Crie o arquivo `pod-ubuntu-limitado.yaml`. 426 | 427 | ```yaml 428 | apiVersion: v1 429 | kind: Pod 430 | metadata: 431 | name: ubuntu 432 | spec: 433 | containers: 434 | - name: ubuntu 435 | image: ubuntu 436 | args: 437 | - sleep 438 | - infinity 439 | resources: 440 | limits: 441 | memory: "128Mi" 442 | cpu: "0.5" 443 | requests: 444 | memory: "64Mi" 445 | cpu: "0.3" 446 | ``` 447 | 448 | Olha essa sacadinha do parâmetro `infinity`, ele faz o container esperar para sempre e assim, se manter em execução. 449 | 450 | Agora vamos criar o Pod. 451 | 452 | ```bash 453 | kubectl create -f pod-ubuntu-limitado.yaml 454 | ``` 455 | 456 | Agora vamos verificar se o Pod foi criado. 457 | 458 | ```bash 459 | kubectl get pods 460 | ``` 461 | 462 | Agora vamos para dentro do container. 463 | 464 | ```bash 465 | kubectl exec -it ubuntu -- bash 466 | ``` 467 | 468 | Agora vamos instalar o comando `stress`. 469 | 470 | ```bash 471 | apt update 472 | apt install -y stress 473 | ``` 474 | 475 | Agora vamos executar o comando `stress` para consumir memória. 476 | 477 | ```bash 478 | stress --vm 1 --vm-bytes 100M 479 | ``` 480 | 481 | Até aqui tudo bem, pois definimos o limite de memória em 128Mi, e o comando `stress` está consumindo 100M, então está tudo certo. 482 | 483 | Vamos aumentar o consumo de memória para 200M. 484 | 485 | ```bash 486 | stress --vm 1 --vm-bytes 200M 487 | ``` 488 | 489 | Veja que o comando `stress` não consegue consumir 200M, pois o limite de memória é 128Mi, e 128Mi é menor que 200M e com isso tomamos o erro e o comando `stress` é interrompido. 490 | 491 | Atigimos o nosso objetivo, atingimos o limite do nosso container! :D 492 | 493 | Quer brincar um pouco mais com o comando `stress`? Veja o `--help` dele. 494 | 495 | ```bash 496 | stress --help 497 | ``` 498 | 499 | Ele traz várias opções para você brincar com o consumo de memória e CPU. 500 | 501 | 502 |   503 | 504 | ### Adicionando um volume EmptyDir no Pod 505 | 506 | Primeira coisa, nesse momento não é o momento de entrar em maiores detalhes sobre volumes, nós teremos um dia inteiro para falar sobre volumes, então não se preocupe com isso agora. 507 | 508 | O dia de hoje é para que possamos ficar bastante confortável com os Pods, desde sua criação, administração, execução de comandos, etc. 509 | 510 | Então, vamos criar um Pod com um volume EmptyDir. 511 | 512 | Antes, o que é um volume EmptyDir? 513 | 514 | Um volume do tipo EmptyDir é um volume que é criado no momento em que o Pod é criado, e ele é destruído quando o Pod é destruído, ou seja, ele é um volume temporário. 515 | 516 | No dia-a-dia, você não vai usar muito esse tipo de volume, mas é importante que você saiba que ele existe. Um dos casos de uso mais comuns é quando você precisa compartilhar dados entre os containers de um Pod. Imagina que você tem dois containers em um Pod e um deles possui um diretório com dados, e você quer que o outro container tenha acesso a esses dados. Nesse caso, você pode criar um volume do tipo EmptyDir e compartilhar esse volume entre os dois containers. 517 | 518 | Chame o arquivo de `pod-emptydir.yaml`. 519 | 520 | ```yaml 521 | apiVersion: v1 # versão da API do Kubernetes 522 | kind: Pod # tipo de objeto que estamos criando 523 | metadata: # metadados do Pod 524 | name: giropops # nome do Pod 525 | spec: # especificação do Pod 526 | containers: # lista de containers 527 | - name: girus # nome do container 528 | image: ubuntu # imagem do container 529 | args: # argumentos que serão passados para o container 530 | - sleep # usando o comando sleep para manter o container em execução 531 | - infinity # o argumento infinity faz o container esperar para sempre 532 | volumeMounts: # lista de volumes que serão montados no container 533 | - name: primeiro-emptydir # nome do volume 534 | mountPath: /giropops # diretório onde o volume será montado 535 | volumes: # lista de volumes 536 | - name: primeiro-emptydir # nome do volume 537 | emptyDir: # tipo do volume 538 | sizeLimit: 256Mi # tamanho máximo do volume 539 | ``` 540 | 541 | Agora vamos criar o Pod. 542 | 543 | ```bash 544 | kubectl create -f pod-emptydir.yaml 545 | ``` 546 | 547 | Agora vamos verificar se o Pod foi criado. 548 | 549 | ```bash 550 | kubectl get pods 551 | ``` 552 | 553 | Você pode ver a saída do comando `kubectl describe pod giropops` para ver o volume que foi criado. 554 | 555 | ```bash 556 | kubectl describe pod giropops 557 | ``` 558 | 559 | ```bash 560 | Volumes: 561 | primeiro-emptydir: 562 | Type: EmptyDir (a temporary directory that shares a pod's lifetime) 563 | Medium: 564 | SizeLimit: 256Mi 565 | ``` 566 | 567 | Agora vamos para dentro do container. 568 | 569 | ```bash 570 | kubectl exec -it giropops -- bash 571 | ``` 572 | 573 | Agora vamos criar um arquivo dentro do diretório `/giropops`. 574 | 575 | ```bash 576 | touch /giropops/FUNCIONAAAAAA 577 | ``` 578 | 579 | Pronto, o nosso arquivo foi criado dentro do diretório `/giropops`, que é um diretório dentro do volume do tipo EmptyDir. 580 | 581 | Se você digitar `mount`, vai ver que o diretório `/giropops` está montado certinho dentro de nosso container. 582 | 583 | Pronto, agora você já sabe criar um Pod com um volume do tipo EmptyDir. :) 584 | 585 | Lembrando mais uma vez que ainda vamos ver muito, mas muito mais sobre volumes, então não se preocupe com isso agora. 586 | 587 |   588 | -------------------------------------------------------------------------------- /pt/day-4/files/nginx-deployment.yaml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /pt/day-4/files/nginx-liveness.yaml: -------------------------------------------------------------------------------- 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 é onde vamos adicionar a nossa livenessProbe 29 | httpGet: # Aqui vamos utilizar o httpGet, onde vamos se conectar ao container através do protocolo HTTP 30 | path: /giropops # Qual o endpoint que vamos utilizar para se conectar ao container 31 | port: 80 # Qual porta TCP vamos utilizar para se conectar ao container 32 | initialDelaySeconds: 10 # Quantos segundos vamos esperar para executar a primeira verificação 33 | periodSeconds: 10 # A cada quantos segundos vamos executar a verificação 34 | timeoutSeconds: 5 # Quantos segundos vamos esperar para considerar que a verificação falhou 35 | failureThreshold: 3 # Quantos falhas consecutivas vamos aceitar antes de reiniciar o container 36 | -------------------------------------------------------------------------------- /pt/day-4/files/nginx-readiness.yaml: -------------------------------------------------------------------------------- 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: # Onde definimos a nossa probe de leitura 29 | httpGet: # O tipo de teste que iremos executar, neste caso, iremos executar um teste HTTP 30 | path: /giropops # O caminho que iremos testar 31 | port: 80 # A porta que iremos testar 32 | initialDelaySeconds: 10 # O tempo que iremos esperar para executar a primeira vez a probe 33 | periodSeconds: 10 # De quanto em quanto tempo iremos executar a probe 34 | timeoutSeconds: 5 # O tempo que iremos esperar para considerar que a probe falhou 35 | successThreshold: 2 # O número de vezes que a probe precisa passar para considerar que o container está pronto 36 | failureThreshold: 3 # O número de vezes que a probe precisa falhar para considerar que o container não está pronto 37 | -------------------------------------------------------------------------------- /pt/day-4/files/nginx-replicaset.yaml: -------------------------------------------------------------------------------- 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.3 19 | name: nginx 20 | resources: 21 | limits: 22 | cpu: "0.5" 23 | memory: 256Mi 24 | requests: 25 | cpu: 0.25 26 | memory: 128Mi 27 | -------------------------------------------------------------------------------- /pt/day-4/files/nginx-startup.yaml: -------------------------------------------------------------------------------- 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: # Onde definimos a nossa probe de inicialização 29 | httpGet: # O tipo de teste que iremos executar, neste caso, iremos executar um teste HTTP 30 | path: / # O caminho que iremos testar 31 | port: 80 # A porta que iremos testar 32 | initialDelaySeconds: 10 # O tempo que iremos esperar para executar a primeira vez a probe 33 | periodSeconds: 10 # De quanto em quanto tempo iremos executar a probe 34 | timeoutSeconds: 5 # O tempo que iremos esperar para considerar que a probe falhou 35 | successThreshold: 1 # O número de vezes que a probe precisa passar para considerar que o container está pronto 36 | failureThreshold: 1 # O número de vezes que a probe precisa falhar para considerar que o container não está pronto 37 | -------------------------------------------------------------------------------- /pt/day-4/files/nginx-todas-probes.yaml: -------------------------------------------------------------------------------- 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: # Onde definimos a nossa probe de vida 29 | exec: # O tipo exec é utilizado quando queremos executar algo dentro do container. 30 | command: # Onde iremos definir qual comando iremos executar 31 | - curl 32 | - -f 33 | - http://localhost:80/ 34 | initialDelaySeconds: 10 # O tempo que iremos esperar para executar a primeira vez a probe 35 | periodSeconds: 10 # De quanto em quanto tempo iremos executar a probe 36 | timeoutSeconds: 5 # O tempo que iremos esperar para considerar que a probe falhou 37 | successThreshold: 1 # O número de vezes que a probe precisa passar para considerar que o container está pronto 38 | failureThreshold: 3 # O número de vezes que a probe precisa falhar para considerar que o container não está pronto 39 | readinessProbe: # Onde definimos a nossa probe de prontidão 40 | httpGet: # O tipo de teste que iremos executar, neste caso, iremos executar um teste HTTP 41 | path: / # O caminho que iremos testar 42 | port: 80 # A porta que iremos testar 43 | initialDelaySeconds: 10 # O tempo que iremos esperar para executar a primeira vez a probe 44 | periodSeconds: 10 # De quanto em quanto tempo iremos executar a probe 45 | timeoutSeconds: 5 # O tempo que iremos esperar para considerar que a probe falhou 46 | successThreshold: 1 # O número de vezes que a probe precisa passar para considerar que o container está pronto 47 | failureThreshold: 3 # O número de vezes que a probe precisa falhar para considerar que o container não está pronto 48 | startupProbe: # Onde definimos a nossa probe de inicialização 49 | tcpSocket: # O tipo de teste que iremos executar, neste caso, iremos executar um teste TCP 50 | port: 80 # A porta que iremos testar 51 | initialDelaySeconds: 10 # O tempo que iremos esperar para executar a primeira vez a probe 52 | periodSeconds: 10 # De quanto em quanto tempo iremos executar a probe 53 | timeoutSeconds: 5 # O tempo que iremos esperar para considerar que a probe falhou 54 | successThreshold: 1 # O número de vezes que a probe precisa passar para considerar que o container está pronto 55 | failureThreshold: 3 # O número de vezes que a probe precisa falhar para considerar que o container não está pronto 56 | -------------------------------------------------------------------------------- /pt/day-4/files/node-exporter-daemonset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 # Versão da API do Kubernetes do objeto 2 | kind: DaemonSet # Tipo do objeto 3 | metadata: # Informações sobre o objeto 4 | name: node-exporter # Nome do objeto 5 | spec: # Especificação do objeto 6 | selector: # Seletor do objeto 7 | matchLabels: # Labels que serão utilizadas para selecionar os Pods 8 | app: node-exporter # Label que será utilizada para selecionar os Pods 9 | template: # Template do objeto 10 | metadata: # Informações sobre o objeto 11 | labels: # Labels que serão adicionadas aos Pods 12 | app: node-exporter # Label que será adicionada aos Pods 13 | spec: # Especificação do objeto, no caso, a especificação do Pod 14 | hostNetwork: true # Habilita o uso da rede do host, usar com cuidado 15 | containers: # Lista de contêineres que serão executados no Pod 16 | - name: node-exporter # Nome do contêiner 17 | image: prom/node-exporter:latest # Imagem do contêiner 18 | ports: # Lista de portas que serão expostas no contêiner 19 | - containerPort: 9100 # Porta que será exposta no contêiner 20 | hostPort: 9100 # Porta que será exposta no host 21 | volumeMounts: # Lista de volumes que serão montados no contêiner, pois o node-exporter precisa de acesso ao /proc e /sys 22 | - name: proc # Nome do volume 23 | mountPath: /host/proc # Caminho onde o volume será montado no contêiner 24 | readOnly: true # Habilita o modo de leitura apenas 25 | - name: sys # Nome do volume 26 | mountPath: /host/sys # Caminho onde o volume será montado no contêiner 27 | readOnly: true # Habilita o modo de leitura apenas 28 | volumes: # Lista de volumes que serão utilizados no Pod 29 | - name: proc # Nome do volume 30 | hostPath: # Tipo de volume 31 | path: /proc # Caminho do volume no host 32 | - name: sys # Nome do volume 33 | hostPath: # Tipo de volume 34 | path: /sys # Caminho do volume no host -------------------------------------------------------------------------------- /pt/day-4/nginx-daemonset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | labels: 5 | app: node-exporter-daemonset 6 | name: node-exporter-daemonset 7 | spec: 8 | selector: 9 | matchLabels: 10 | app: node-exporter-daemonset 11 | template: 12 | metadata: 13 | labels: 14 | app: node-exporter-daemonset 15 | spec: 16 | hostNetwork: true 17 | containers: 18 | - name: node-exporter 19 | image: prom/node-exporter:v1.4.1 20 | ports: 21 | - containerPort: 9100 22 | hostPort: 9100 23 | volumeMounts: 24 | - name: proc 25 | mountPath: /host/proc 26 | readOnly: true 27 | - name: sys 28 | mountPath: /host/sys 29 | readOnly: true 30 | volumes: 31 | - name: proc 32 | hostPath: 33 | path: /proc 34 | - name: sys 35 | hostPath: 36 | path: /sys 37 | -------------------------------------------------------------------------------- /pt/day-4/nginx-deployment.yaml: -------------------------------------------------------------------------------- 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:1.19.1 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: 29 | exec: 30 | command: 31 | - curl 32 | - -f 33 | - http://localhost:80/ 34 | initialDelaySeconds: 10 35 | periodSeconds: 10 36 | successThreshold: 1 37 | failureThreshold: 2 38 | timeoutSeconds: 5 39 | readinessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | initialDelaySeconds: 10 44 | periodSeconds: 10 45 | successThreshold: 1 46 | failureThreshold: 2 47 | timeoutSeconds: 5 48 | startupProbe: 49 | tcpSocket: 50 | port: 80 51 | initialDelaySeconds: 10 52 | periodSeconds: 10 53 | successThreshold: 1 54 | failureThreshold: 2 55 | timeoutSeconds: 5 56 | -------------------------------------------------------------------------------- /pt/day-4/nginx-replicaset.yaml: -------------------------------------------------------------------------------- 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 | - name: nginx 19 | image: nginx:1.19.2 20 | resources: 21 | limits: 22 | cpu: 0.5 23 | memory: 256Mi 24 | requests: 25 | cpu: 0.3 26 | memory: 126Mi 27 | -------------------------------------------------------------------------------- /pt/day-6/files/giropops-senhas-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: giropops-senhas 6 | name: giropops-senhas 7 | spec: 8 | replicas: 3 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 | ports: 21 | - containerPort: 5000 22 | imagePullPolicy: Always 23 | resources: 24 | limits: 25 | memory: "256Mi" 26 | cpu: "500m" 27 | requests: 28 | memory: "128Mi" 29 | cpu: "250m" -------------------------------------------------------------------------------- /pt/day-6/files/giropops-senhas-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: giropops-senhas 5 | labels: 6 | app: giropops-senhas 7 | spec: 8 | selector: 9 | app: giropops-senhas 10 | ports: 11 | - protocol: TCP 12 | port: 80 13 | targetPort: 5000 14 | name: tcp-app 15 | type: ClusterIP -------------------------------------------------------------------------------- /pt/day-6/files/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod 5 | spec: 6 | containers: 7 | - name: nginx 8 | image: nginx:latest 9 | ports: 10 | - containerPort: 80 11 | volumeMounts: 12 | - name: meu-pvc 13 | mountPath: /usr/share/nginx/html 14 | volumes: 15 | - name: meu-pvc 16 | persistentVolumeClaim: 17 | claimName: meu-pvc -------------------------------------------------------------------------------- /pt/day-6/files/pv-nfs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 # Versão da API do Kubernetes 2 | kind: PersistentVolume # Tipo de objeto que estamos criando, no caso um PersistentVolume 3 | metadata: # Informações sobre o objeto 4 | name: meu-pv-nfs # Nome do nosso PV 5 | labels: 6 | storage: nfs 7 | spec: # Especificações do nosso PV 8 | capacity: # Capacidade do PV 9 | storage: 1Gi # 1 Gigabyte de armazenamento 10 | accessModes: # Modos de acesso ao PV 11 | - ReadWriteOnce # Modo de acesso ReadWriteOnce, ou seja, o PV pode ser montado como leitura e escrita por um único nó 12 | persistentVolumeReclaimPolicy: Retain # Política de reivindicação do PV, ou seja, o PV não será excluído quando o PVC for excluído 13 | nfs: # Tipo de armazenamento que vamos utilizar, no caso o NFS 14 | server: 192.168.0.219 # Endereço do servidor NFS 15 | path: "/mnt/nfs" # Compartilhamento do servidor NFS 16 | storageClassName: nfs # Nome da classe de armazenamento que será utilizada -------------------------------------------------------------------------------- /pt/day-6/files/pv.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 # Versão da API do Kubernetes 2 | kind: PersistentVolume # Tipo de objeto que estamos criando, no caso um PersistentVolume 3 | metadata: # Informações sobre o objeto 4 | name: meu-pv # Nome do nosso PV 5 | labels: 6 | storage: local 7 | spec: # Especificações do nosso PV 8 | capacity: # Capacidade do PV 9 | storage: 1Gi # 1 Gigabyte de armazenamento 10 | accessModes: # Modos de acesso ao PV 11 | - ReadWriteOnce # Modo de acesso ReadWriteOnce, ou seja, o PV pode ser montado como leitura e escrita por um único nó 12 | persistentVolumeReclaimPolicy: Retain # Política de reivindicação do PV, ou seja, o PV não será excluído quando o PVC for excluído 13 | hostPath: # Tipo de armazenamento que vamos utilizar, no caso um hostPath 14 | path: "/mnt/data" # Caminho do hostPath, do nosso nó, onde o PV será criado 15 | storageClassName: standard # Nome da classe de armazenamento que será utilizada 16 | -------------------------------------------------------------------------------- /pt/day-6/files/pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 # versão da API do Kubernetes 2 | kind: PersistentVolumeClaim # tipo de recurso, no caso, um PersistentVolumeClaim 3 | metadata: # metadados do recurso 4 | name: meu-pvc # nome do PVC 5 | spec: # especificação do PVC 6 | accessModes: # modo de acesso ao volume 7 | - ReadWriteOnce # modo de acesso RWO, ou seja, somente leitura e escrita por um nó 8 | resources: # recursos do PVC 9 | requests: # solicitação de recursos 10 | storage: 1Gi # tamanho do volume que ele vai solicitar 11 | storageClassName: nfs # nome da classe de armazenamento que será utilizada 12 | selector: # seletor de labels 13 | matchLabels: # labels que serão utilizadas para selecionar o PV 14 | storage: nfs # label que será utilizada para selecionar o PV -------------------------------------------------------------------------------- /pt/day-6/files/storageclass-nfs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 # Versão da API do Kubernetes 2 | kind: StorageClass # Tipo de objeto que estamos criando, no caso um StorageClass 3 | metadata: # Informações sobre o objeto 4 | name: nfs # Nome do nosso StorageClass 5 | provisioner: kubernetes.io/no-provisioner # Provisionador que será utilizado para criar o PV 6 | reclaimPolicy: Retain # Política de reivindicação do PV, ou seja, o PV não será excluído quando o PVC for excluído 7 | volumeBindingMode: WaitForFirstConsumer 8 | parameters: # Parâmetros que serão utilizados pelo provisionador 9 | archiveOnDelete: "false" # Parâmetro que indica se os dados do PV devem ser arquivados quando o PV for excluído -------------------------------------------------------------------------------- /pt/day-6/files/storageclass.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: giropops 5 | provisioner: kubernetes.io/no-provisioner 6 | reclaimPolicy: Retain 7 | volumeBindingMode: WaitForFirstConsumer -------------------------------------------------------------------------------- /pt/day-7/files/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 # Como estamos criando um Headless Service, não queremos que ele tenha um IP, então definimos o clusterIP como None 12 | selector: 13 | app: nginx -------------------------------------------------------------------------------- /pt/day-7/files/nginx-clusterip-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx 5 | labels: 6 | app: nginx 7 | env: dev 8 | spec: 9 | selector: 10 | app: nginx 11 | ports: 12 | - port: 80 13 | name: http 14 | targetPort: 80 15 | type: ClusterIP -------------------------------------------------------------------------------- /pt/day-7/files/nginx-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | template: 11 | metadata: 12 | labels: 13 | app: nginx 14 | env: dev 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx 19 | ports: 20 | - containerPort: 80 21 | name: http -------------------------------------------------------------------------------- /pt/day-7/files/nginx-loadbalancer-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-loadbalancer 5 | labels: 6 | app: nginx 7 | env: dev 8 | spec: 9 | selector: 10 | app: nginx 11 | ports: 12 | - port: 80 13 | name: http 14 | targetPort: 80 15 | type: LoadBalancer -------------------------------------------------------------------------------- /pt/day-7/files/nginx-nodeport-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-nodeport 5 | labels: 6 | app: nginx 7 | env: dev 8 | spec: 9 | selector: 10 | app: nginx 11 | ports: 12 | - port: 80 13 | name: http 14 | targetPort: 80 15 | nodePort: 32000 16 | type: NodePort -------------------------------------------------------------------------------- /pt/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:1.22.1 19 | ports: 20 | - containerPort: 80 21 | name: app 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 -------------------------------------------------------------------------------- /pt/day-9/files/app-deployment.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 -------------------------------------------------------------------------------- /pt/day-9/files/app-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: giropops-senhas 5 | labels: 6 | app: giropops-senhas 7 | spec: 8 | selector: 9 | app: giropops-senhas 10 | ports: 11 | - protocol: TCP 12 | port: 5000 13 | targetPort: 5000 14 | name: tcp-app 15 | type: ClusterIP -------------------------------------------------------------------------------- /pt/day-9/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 -------------------------------------------------------------------------------- /pt/day-9/files/ingress-2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: giropops-senhas-static 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 -------------------------------------------------------------------------------- /pt/day-9/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 -------------------------------------------------------------------------------- /pt/day-9/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 | - host: giropops.nginx.io 10 | http: 11 | paths: 12 | - path: / 13 | pathType: Prefix 14 | backend: 15 | service: 16 | name: nginx 17 | port: 18 | number: 80 -------------------------------------------------------------------------------- /pt/day-9/files/ingress-5.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: giropops-senhas.io 10 | http: 11 | paths: 12 | - path: / 13 | pathType: Prefix 14 | backend: 15 | service: 16 | name: giropops-senhas 17 | port: 18 | number: 5000 -------------------------------------------------------------------------------- /pt/day-9/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 | ingressClassName: nginx 9 | rules: 10 | - http: 11 | paths: 12 | - path: / 13 | pathType: Prefix 14 | backend: 15 | service: 16 | name: giropops-senhas 17 | port: 18 | number: 5000 -------------------------------------------------------------------------------- /pt/day-9/files/ingress-7.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 | ingressClassName: nginx 9 | rules: 10 | - host: giropops.containers.expert 11 | http: 12 | paths: 13 | - path: / 14 | pathType: Prefix 15 | backend: 16 | service: 17 | name: giropops-senhas 18 | port: 19 | number: 5000 -------------------------------------------------------------------------------- /pt/day-9/files/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 -------------------------------------------------------------------------------- /pt/day-9/files/redis-deployment.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" -------------------------------------------------------------------------------- /pt/day-9/files/redis-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: redis-service 5 | spec: 6 | selector: 7 | app: redis 8 | ports: 9 | - protocol: TCP 10 | port: 6379 11 | targetPort: 6379 12 | type: ClusterIP -------------------------------------------------------------------------------- /styles/website.css: -------------------------------------------------------------------------------- 1 | .book-langs-index .inner { 2 | max-width: 800px; 3 | } 4 | 5 | .book-langs-index .inner h3 { 6 | text-align: center; 7 | font-size: 30px; 8 | } 9 | 10 | .book-langs-index .inner .languages li { 11 | font-size: 24px; 12 | } 13 | --------------------------------------------------------------------------------