<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Google Cloud archivos - Geko Cloud</title>
	<atom:link href="https://geko.cloud/es/etiqueta/google-cloud/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>Servicios de consultoría cloud y devops</description>
	<lastBuildDate>Mon, 08 Nov 2021 09:51:10 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.5.9</generator>

<image>
	<url>https://geko.cloud/wp-content/uploads/2021/08/cropped-geko-fav-150x150.png</url>
	<title>Google Cloud archivos - Geko Cloud</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>GCP Cloud SQL &#8211; Recuperando una base de datos eliminada accidentalmente</title>
		<link>https://geko.cloud/es/gcp-cloud-recuperar-base-datos/</link>
					<comments>https://geko.cloud/es/gcp-cloud-recuperar-base-datos/#respond</comments>
		
		<dc:creator><![CDATA[Geko Cloud]]></dc:creator>
		<pubDate>Wed, 10 Mar 2021 09:29:29 +0000</pubDate>
				<category><![CDATA[Labs]]></category>
		<category><![CDATA[Google Cloud]]></category>
		<category><![CDATA[MySQL]]></category>
		<guid isPermaLink="false">https://geko2.factoryfy.com/?p=3953</guid>

					<description><![CDATA[<p>Introducción Todo comenzó con un simple mensaje: «Hola Geko, estamos recibiendo un timeout de conexión con la DB«. Nos llevó menos de 2 minutos descubrir qué estaba pasando: La base de datos se había borrado. Después de llevarnos las manos a la cabeza varias veces, la tarea principal era recuperar los datos (y el servicio). [&#8230;]</p>
<p>La entrada <a href="https://geko.cloud/es/gcp-cloud-recuperar-base-datos/">GCP Cloud SQL &#8211; Recuperando una base de datos eliminada accidentalmente</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Introducción</h2>
<p style="text-align: justify;">Todo comenzó con un simple mensaje: «<em>Hola <a href="https://geko2.factoryfy.com/es/">Geko</a>, estamos recibiendo un timeout de conexión con la DB</em>«. Nos llevó menos de 2 minutos descubrir qué estaba pasando: La <strong>base de datos</strong> se había borrado. Después de llevarnos las manos a la cabeza varias veces, la tarea principal era recuperar los datos (y el servicio). Afortunadamente, Google aplica políticas de copias <strong>de seguridad</strong> que guardan una copia cada día. En <a href="https://geko2.factoryfy.com/es/">Geko </a>todos estamos de acuerdo con esta política. La cosa es que fuimos a buscar las <strong>copias de seguridad</strong>, y la pesadilla comenzó. ¡No había <strong>copias de seguridad</strong>! ¡No había nada! Y entonces descubrimos que las <strong>copias de seguridad</strong> están estrechamente ligadas al propio recurso de la <strong>base de datos</strong>, de modo que si ésta se elimina las <strong>copias de seguridad</strong> también lo harán. <a href="https://cloud.google.com/sql/docs/mysql/delete-instance">Google lo deja bien claro en su documentación de Cloud SQL.</a></p>
<p style="text-align: justify;">
<p><img fetchpriority="high" decoding="async" class="size-full wp-image-5413 aligncenter" src="https://geko.cloud/wp-content/uploads/2021/03/google-warning-min.jpg" alt="Google warning" width="842" height="308" srcset="https://geko.cloud/wp-content/uploads/2021/03/google-warning-min.jpg 842w, https://geko.cloud/wp-content/uploads/2021/03/google-warning-min-300x110.jpg 300w, https://geko.cloud/wp-content/uploads/2021/03/google-warning-min-768x281.jpg 768w" sizes="(max-width: 842px) 100vw, 842px" /></p>
<p style="text-align: justify;">No vamos a profundizar más en el tema de cómo se borró la <strong>base de datos</strong>. Simplemente decir que fue un <strong>proceso automatizado</strong> que detectó un cambio en el tamaño de disco y, cuando trataba de reemplazar el valor con el anterior (que era un valor menor) se <strong>requirió un reemplazo completo</strong> de la <strong>base de datos</strong>. No hubo oportunidad para aceptarlo ni para pararlo, por lo que la situación era la que era:</p>
<ul>
<li>No hay <strong>base de datos</strong> == No hay datos</li>
<li>No hay <strong>copias de seguridad</strong></li>
</ul>
<h2>Qué hicimos para resolver la situación</h2>
<p style="text-align: justify;">Incluso cuando Google nos estaba diciendo que las <strong>copias de seguridad</strong> se borran cuando lo hace la <strong>base de datos</strong>, y que todos los hechos apuntaban a esta hipótesis, fuimos obstinados a pesar de todo ello. La interfaz web de <strong>GCP</strong> no nos ofreció forma alguna de recuperar nada, por lo que decidimos continuar investigando por <strong>línea de comandos</strong> (<strong><em>CLI</em></strong> gcloud). <strong>¡Y ésta fue la clave de nuestro éxito!</strong></p>
<p style="text-align: justify;">Teníamos la teoría de que las <strong>copias de seguridad</strong> deberían estar todavía en alguna parte (aún cuando la documentación dice lo contrario), así que comprobamos diferentes tipos de lugares de almacenamiento hasta probar la sección de <strong>copias de seguridad</strong> de <strong>SQL</strong>. Resulta que fuimos lo suficientemente rápidos al comprobar esta sección, y también <strong>sabíamos el nombre de la base de datos borrada</strong>, por lo que fuimos capaces de ejecutar el siguiente comando.</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">$ gcloud sql backups list --instance=deleted-db-name --project our-project
ID             WINDOW_START_TIME              ERROR  STATUS
1614876500000  2021-03-04T04:00:00.000+00:00  -      SUCCESSFUL
1614765400000  2021-03-03T04:00:00.000+00:00  -      SUCCESSFUL
1614654300000  2021-03-02T04:00:00.000+00:00  -      SUCCESSFUL
1614543200000  2021-03-01T04:00:00.000+00:00  -      SUCCESSFUL
1614432100000  2021-02-28T04:00:00.000+00:00  -      SUCCESSFUL
1614321000000  2021-02-27T04:00:00.000+00:00  -      SUCCESSFUL
1614210000000  2021-02-26T04:00:00.000+00:00  -      SUCCESSFUL</pre>
</div>
<p style="text-align: justify;">Y ahí estaban! Después de recuperar el aliento y las sonrisas, el <strong>proceso de recuperación</strong> daba comienzo. Todavía no confiábamos plenamente en que esto fuese a funcionar, ya que quizás la lista de copias estaba ahí mientras que los datos ya no. <strong>Nos movimos rápido por</strong><strong>que sabíamos que el tiempo jugaba en nuestra contra, así que inmediatamente creamos una nueva base de datos desde cero y, justo después, iniciamos el proceso de restauración</strong>.</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">$ gcloud sql backups restore 1614876500000 --restore-instance=new-db-from-scratch-name --project our-project --backup-instance=deleted-db-name
All current data on the instance will be lost when the backup is 
restored.

Do you want to continue (Y/n)?  

Restoring Cloud SQL instance...done.                                                                                                                                                                                                        
Restored [https://sqladmin.googleapis.com/sql/v1beta4/projects/our-project/instances/new-db-from-scratch-name]</pre>
</div>
<p style="text-align: justify;">Finalmente, incluso teniendo retroalimentación positiva por parte de <strong>GCP</strong>, todavía no nos creíamos que hubiera funcionado. Teníamos que verificar que los datos efectivamente estaba ahí, y así lo hicimos. Afortunadamente todo se había recuperado, por lo que nuestro siguiente y último paso fue realizar una extracción <strong>SQL</strong> de los datos, de modo que pudiéramos asegurar que teníamos una copia reciente en otra localización diferente.</p>
<h2>Conclusión</h2>
<p style="text-align: justify;">Incluso después de buscar en Google con ahínco y no encontrar ningún resultado que sirviera de ayuda  — ya que todos dicen que no hay nada que hacer — nuestro conocimiento y pasión nos hizo continuar investigando acerca del tema hasta que encontramos la manera. Sabemos que fuimos afortunados al encontrar las <strong>copias de seguridad</strong> todavía ahí, pero también sabemos que fuimos <strong>rápidos</strong>, <strong>metódicos</strong> y <strong>obstinados</strong> al buscar y detectar una solución. Por otra parte, hemos aprendido que no nos podemos fiar de las <strong>copias de seguridad</strong> realizadas por el proveedor, por lo que estamos trabajando actualmente en procedimientos para tener copias en más sitios. <strong>Tenemos muy claro que esta es la primera y última vez que nos sucede esto</strong>.</p>
<p style="text-align: justify;">Además, y al contrario que AWS, como mencionamos anteriormente, GCP relaciona fuertemente el recurso de la <strong>base de datos</strong> con sus <strong>copias de seguridad</strong>. Esto se ha demostrado que puede llegar a ser un gran problema cuando hay que gestionar un borrado accidental. Y a eso hay que sumarle que no es posible copiar o mover las <strong>copias de seguridad</strong> a otros tipos de almacenamiento. A pesar de lo anterior, hay soluciones personalizadas como extraer los datos SQL regularmente y almacenarlos en un <em>bucket</em>, pero no es algo oficial.</p>
<p style="text-align: justify;">Por otra parte, recomendamos encarecidamente ser cautos cuando haya procesos automatizados alrededor. Hasta donde hemos visto, la única forma de <strong>proteger contra eliminación</strong> una <strong>base de datos</strong> en <strong>GCP</strong>, es limitar los permisos. Por ello, la forma de proceder es <strong>eliminar el permiso <em>DELETE</em></strong> de las cuentas (de servicio) que estos <strong>procesos automatizados</strong> usen.</p>
<p><img decoding="async" class="aligncenter wp-image-4117 size-full" src="https://geko2.factoryfy.com/wp-content/uploads/meme.jpg" alt="Joke about GCP. Geko as a strong dog says: I accidentally deleted my DB. I need a backup! ― GCP as a weak dog answers: I deleted your backups when removing the DB. It was not was you was looking for? ― And finally Geko dog replies: Ok... let me find them for you and fix all this mess!" width="468" height="420" /></p>
<p style="text-align: justify;">Afortunadamente siempre puedes contar con el equipo de <a href="https://geko.cloud/es/">Geko</a> (un equipo de ingenieros altamente cualificados), quienes profundizarán en el tema hasta conseguir hacerlo sencillo o solucionarlo para ti. ¡No olvides volver por el <a href="https://geko.cloud/es/blog/labs/">blog de Geko</a> para comprobar qué hay nuevo por aquí! El equipo de <a href="https://geko.cloud/es/">Geko</a> siempre estará más que contento de verte por aquí, y por supuesto</p>
<p style="text-align: center;"><strong><a href="https://geko.cloud/es/contacto/" target="_blank" rel="noopener noreferrer">¡Ponte en contacto con nosotros para más información!</a></strong></p>
<p><a href="https://geko.cloud/es/contacto/"><img decoding="async" class="aligncenter wp-image-3265" src="https://geko2.factoryfy.com/wp-content/uploads/geko-1-300x297.png" alt="" width="80" height="79" /></a></p>
<p>La entrada <a href="https://geko.cloud/es/gcp-cloud-recuperar-base-datos/">GCP Cloud SQL &#8211; Recuperando una base de datos eliminada accidentalmente</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://geko.cloud/es/gcp-cloud-recuperar-base-datos/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>GCP/GKE &#8211; Nuevo sistema de logging</title>
		<link>https://geko.cloud/es/gcp-gke-nuevo-sistema-de-logging/</link>
					<comments>https://geko.cloud/es/gcp-gke-nuevo-sistema-de-logging/#respond</comments>
		
		<dc:creator><![CDATA[Geko Cloud]]></dc:creator>
		<pubDate>Mon, 07 Sep 2020 05:27:42 +0000</pubDate>
				<category><![CDATA[Noticias]]></category>
		<category><![CDATA[GKE]]></category>
		<category><![CDATA[Google Cloud]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<guid isPermaLink="false">https://geko2.factoryfy.com/?p=2388</guid>

					<description><![CDATA[<p>Introducción Es muy probable que tengas un clúster de GKE en la versión v1.15 y durante varios meses no hayas sufrido problemas cuando, de repente, los logs han dejado de recibirse. Estás usando el sistema de logging que provee el sistema por defecto, por lo que compruebas la página de status de GCP pero todo [&#8230;]</p>
<p>La entrada <a href="https://geko.cloud/es/gcp-gke-nuevo-sistema-de-logging/">GCP/GKE &#8211; Nuevo sistema de logging</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Introducción</h2>
<p>Es muy probable que tengas un clúster de <a href="https://cloud.google.com/kubernetes-engine/docs/concepts/kubernetes-engine-overview">GKE</a> en la versión v1.15 y durante varios meses no hayas sufrido problemas cuando, de repente, los logs han dejado de recibirse. Estás usando el sistema de logging que provee el sistema por defecto, por lo que compruebas la <a href="https://status.cloud.google.com/">página de status de GCP</a> pero todo está funcionando correctamente. Además sabes que no has modificado nada en el clúster antes de que se detuviese la recepción de logs, pero al mismo tiempo sospechas que tiene que estás causado por algo en tu parte (en nuestro caso nos dimos cuenta de que no estaba sucediendo en otros clústeres que gestionamos).</p>
<p>Si la anterior historia te resulta familiar, continúa leyendo ya que este artículo cubrirá desde cómo detectarlo hasta la solución que hará que los logs del clúster se vuelvan a recibir.</p>
<h2>1. Síntomas</h2>
<ol style="list-style-type: none; color: #3a3a3a; font-weight: 400;">
<li style="list-style-type: none;">
<ol style="list-style-type: none; color: #3a3a3a; font-weight: 400;">
<li>&#8211; El síntoma principal que verás es la repentina y completa ausencia de logs en <a href="https://en.wikipedia.org/wiki/Stackdriver">Stackdriver</a>, los cuales deberían estar recibiéndose -como de costumbre- desde los pods de tu clúster.</li>
</ol>
</li>
</ol>
<p>&nbsp;</p>
<ol style="list-style-type: none; color: #3a3a3a; font-weight: 400;">
<li>&#8211; Además del hecho anterior, podrás descubrir que ya no hay agentes de <a href="https://en.wikipedia.org/wiki/Fluentd">Fluentd</a> en tu clúster.
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">$ kubectl get daemonset -n kube-system | grep -i fluentd

</pre>
</div>
</li>
<li>&#8211; Por otra parte todos los nodos de tu clúster tienen la etiqueta («label») <strong>beta.kubernetes.io/fluentd-ds-ready=true</strong>, la cual es requerida por los agentes de Fluentd para saber en qué nodos deben desplegarse.
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">$ kubectl get nodes
NAME                           STATUS   ROLES    AGE     VERSION
gke-cluster-node-93c020-7rjq   Ready    none     14h     v1.15.11-gke.15
gke-cluster-node-93c020-9w22   Ready    none     23h     v1.15.11-gke.15
gke-cluster-node-93c020-jdbt   Ready    none     47h     v1.15.11-gke.15
gke-cluster-node-93c020-jvcl   Ready    none     3h17m   v1.15.11-gke.15

$ kubectl describe node gke-cluster-node-93c020-7rjq | grep -i fluentd-ds-ready
       beta.kubernetes.io/fluentd-ds-ready=true

$ # Haz lo mismo para los nodos restantes para asegurar que todos ellos están adecuadamente etiquetados</pre>
</div>
</li>
<li>&#8211; Tu clúster de GKE está actualmente en la versión v1.15 o superior.</li>
</ol>
<h2>2. Diagnóstico</h2>
<p>Lo que está sucediendo es que Google está descatalogando a marchas forzadas el antiguo sistema de monitorización/logging. El nuevo sistema que lo reemplaza se llama <a href="https://cloud.google.com/stackdriver/docs/solutions/gke">Cloud Operations for GKE</a> que (para nuestro caso) hace básicamente lo mismo. Una vez dicho eso, cabe mencionar que hay algunas diferencias que deberás tener en cuenta cuando realices búsquedas (como por ejemplo cambios en los nombres de las métricas), y que todas ellas las encontrarás en la <a href="https://cloud.google.com/stackdriver/docs/solutions/gke/migration#what-is-changing">guía de migración</a>.</p>
<h2>3. Tratamiento</h2>
<h3>Etiquetar los nodos del clúster</h3>
<p>Si te encontraste en pasos previos que uno o varios de los nodos de tu clúster no están etiquetados, ¡hazlo ahora!</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">$ kubectl label node $NODE_NAME beta.kubernetes.io/fluentd-ds-ready=true</pre>
</div>
<h3>Obtén el nombre de tu clúster</h3>
<p>Lista los clústeres disponibles.</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">$ gcloud container clusters list
NAME        LOCATION        MASTER_VERSION  MASTER_IP    MACHINE_TYPE   NODE_VERSION    NUM_NODES  STATUS
my-cluster  europe-east1-a  1.15.12-gke.2   34.35.36.37  n1-standard-2  1.15.11-gke.15  4          RUNNING
</pre>
</div>
<h3>Deshabilita el servicio de logging para tu clúster</h3>
<p>Actualiza la configuración de tu clúster para establecer el servicio de logging al valor <em>none.</em></p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">$ gcloud container clusters update my-cluster --logging-service none</pre>
</div>
<h3>Habilita de nuevo el servicio de logging para tu clúster</h3>
<p>Actualiza la configuración de tu clúster para volver a establecer el servicio de logging al que hay por defecto.</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">$ gcloud container clusters update my-cluster --logging-service logging.googleapis.com</pre>
</div>
<p><strong>ATENCIÓN:</strong> Obtendrás un mensaje de error informándote que no es posible habilitarlo debido a la descatalogación. Esta es la forma por la que finalmente nos dimos cuenta dónde estaba el problema. Simplemente sigue adelante, vas en la dirección correcta.</p>
<h3>Verifica que el estado de la migración es el esperado</h3>
<p>Abre la <a href="https://console.cloud.google.com/monitoring">sección de monitorización (monitoring) de interfaz web de GCP</a> y dirígete a la sub-sección de configuración (Settings). Encontrarás una pestaña llamada «Kubernetes Migration Status» que debería verse como a continuación.</p>
<p><img loading="lazy" decoding="async" class="wp-image-2435 size-full alignnone" src="https://geko2.factoryfy.com/wp-content/uploads/kubernetes-migration-dashboard.png" alt="" width="871" height="554" /></p>
<h3>Habilitar completamente el servicio de loggin y monitorización para tu clúster</h3>
<p>Abre la <a href="https://console.cloud.google.com/kubernetes/list">lista de clústeres de GKE</a> haz clic en el nombre del clúster donde quieres configurar el nuevo sistema de logging. Una vez veas la configuración del clúster, haz clic en el botón EDITAR como se muestra a continuación.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-2437 alignnone" src="https://geko2.factoryfy.com/wp-content/uploads/edit-cluster.png" alt="" width="731" height="213" /></p>
<p>Desliza hacia abajo hasta encontrar el parámetro <span class="p6n-form-label"><span class="p6n-form-label-transclude"><strong>Kubernetes Engine Monitoring</strong> y, haciendo clic en el desplegable, selecciona la opción <strong>Almacenamiento de registros y supervisión del sistema y las cargas de trabajo</strong> (<strong>System and workload logging and monitoring)</strong>.</span></span></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2439" src="https://geko2.factoryfy.com/wp-content/uploads/monitoring-dropdown.png" alt="" width="463" height="131" /></p>
<p><strong>IMPORTANTE: </strong>No olvides guardas los cambios usando el botón que hay al final.</p>
<h5>Y ya está! Tu clúster volverá a recibir de nuevo los logs!</h5>
<p>&nbsp;</p>
<h2>Conclusión</h2>
<p>Como probablemente ya sabrás Google Cloud Platform está todavía en fase beta, por lo que habitualmente encontrarás algunos cambios que harán que fallen tus sistemas en funcionamiento. Tienes dos opciones en este punto: Por un lado puedes mantenerte actualizado acerca de todos los cambios y descatalogaciones futuras. Por otro, puedes limitarte a ir arreglar las cosas según vayan surgiendo, pero ten en cuenta que siempre estarás luchando contra los problemas a ciegas.</p>
<p>Hay una tercera opción (que podría ser la primera), que consiste en consultar regularmente el <a href="https://geko.cloud/es/blog/">blog de Geko</a> y verificar si ya nos hemos tratado con el problema que te estás encontrando. El equipo de Geko siempre estará contento de verte aquí <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p><a href="https://geko.cloud/es/contacto/" target="_blank" rel="noopener noreferrer">Contáctanos para más información!</a></p>
<p>La entrada <a href="https://geko.cloud/es/gcp-gke-nuevo-sistema-de-logging/">GCP/GKE &#8211; Nuevo sistema de logging</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://geko.cloud/es/gcp-gke-nuevo-sistema-de-logging/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Actualización del módulo Terraform en los clústeres públicos de GKE</title>
		<link>https://geko.cloud/es/actualizacion-modulo-terraform-clusteres-publicos-gke/</link>
					<comments>https://geko.cloud/es/actualizacion-modulo-terraform-clusteres-publicos-gke/#respond</comments>
		
		<dc:creator><![CDATA[Geko Cloud]]></dc:creator>
		<pubDate>Wed, 13 May 2020 06:24:40 +0000</pubDate>
				<category><![CDATA[Noticias]]></category>
		<category><![CDATA[GKE]]></category>
		<category><![CDATA[Google Cloud]]></category>
		<category><![CDATA[Terraform]]></category>
		<guid isPermaLink="false">https://geko2.factoryfy.com/?p=1831</guid>

					<description><![CDATA[<p>Introducción De vez en cuando, Google introduce nuevas características y cambios que a veces también obligan a los módulos de Terraform a actualizarse. En Geko, estábamos usando el módulo GKE para la implementación y administración de clústeres públicos en la versión 5.x. Hace unos días, cuando planeamos actualizar algunos parámetros, descubrimos que Google había eliminado [&#8230;]</p>
<p>La entrada <a href="https://geko.cloud/es/actualizacion-modulo-terraform-clusteres-publicos-gke/">Actualización del módulo Terraform en los clústeres públicos de GKE</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3>Introducción</h3>
<p>De vez en cuando, Google introduce nuevas características y cambios que a veces también obligan a los <a href="https://www.terraform.io/docs/configuration/modules.html">módulos de Terraform</a> a actualizarse. En <strong><a href="http://geko.cloud/es">Geko</a></strong>, estábamos usando el módulo <a href="https://registry.terraform.io/modules/terraform-google-modules/kubernetes-engine/google/5.1.1/submodules/beta-public-cluster">GKE para la implementación y administración de clústeres públicos en la versión 5.x</a>. Hace unos días, cuando planeamos actualizar algunos parámetros, descubrimos que Google había eliminado la compatibilidad con el panel de control de Kubernetes. Estaba completamente en desuso y el módulo estaba fallando debido a ello, por lo que nos vimos obligados a actualizar el módulo para cumplir con las nuevas condiciones. Hubo hasta 3 actualizaciones de versiones principales disponibles, por lo que decidimos probarlo y usar la última. Sin embargo, no era una solución independiente, ya que requería gestionar las incoherencias del estado de Terraform.</p>
<p>El objetivo de este laboratorio es aprender cómo actualizar el módulo oficial Terraform destinado a implementar y administrar un clúster GKE público. Nos ocuparemos especialmente de los cambios de ruptura del módulo (<a href="https://registry.terraform.io/modules/terraform-google-modules/kubernetes-engine/google/8.1.0/submodules/beta-public-cluster">kubernetes-engine.beta-public-cluster</a>), y lograremos obtener el estado consistente que teníamos antes de la falla que precedió a la actualización.</p>
<p><strong>Tiempo estimado para terminar este laboratorio:</strong> ~ 20 minutos</p>
<h3>1. Eliminar los recursos anteriores</h3>
<p><strong>¡Se recomienda encarecidamente realizar una copia de seguridad de archivos tfstate antes de continuar!</strong></p>
<p>Es especialmente importante eliminar todos los recursos conflictivos del tfstate de Terraform ya que están vinculados entre ellos como dependencias. El objetivo aquí es eliminar cualquier enlace obsoleto antes de importarlo nuevamente desde la «imagen» actual que ya se ha desplegado.</p>
<p>Los componentes principales en un clúster de Kubernetes son las redes (y subredes), el grupo de nodos y el clúster en sí. Centrémonos en ellos.</p>
<div class="wp-block-codemirror-blocks code-block">
<pre class="CodeMirror" data-setting="{">terraform state rm module.gke.google_container_cluster.primary
terraform state rm module.gke.google_container_node_pool.pools[0]
terraform state rm module.vpc.google_compute_network.network
terraform state rm module.vpc.google_compute_subnetwork.subnetwork[0]
terraform state rm module.vpc.google_compute_subnetwork.subnetwork[1]</pre>
</div>
<h3>2. Actualizar versiones</h3>
<p>Una vez eliminados los estados anteriores, el siguiente paso es configurar la última versión los módulos requeridos. Para el módulo GKE, la última versión disponible a fecha de hoy es 8.1.0, pero se permite aplicar automáticamente actualizaciones menores («~&gt;»).</p>
<h5>Actualizar el módulo clúster GKE</h5>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{"> module "gke" {
   source  = "terraform-google-modules/kubernetes-engine/google//modules/beta-public-cluster"
-  version = "~&gt; 5.0"
+  version = "~&gt; 8.1"
</pre>
</div>
<h5>Actualizar el módulo VPC</h5>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{"> module "vpc" {
-  source  = "github.com/terraform-google-modules/terraform-google-network?ref=v1.1.0"
+  source  = "github.com/terraform-google-modules/terraform-google-network?ref=v2.3.0"</pre>
</div>
<h5>Comprobar los nuevos recursos</h5>
<p>Para saber si los nuevos recursos han experimentado un cambio de nombre (debido a la actualización de los módulos), se recomienda encarecidamente lanzar un <a href="https://www.terraform.io/docs/commands/plan.html">plan de Terraform.</a></p>
<p>En este caso, se ha encontrado que la jerarquía interna de algunos módulos y también los índices de la lista han cambiado.</p>
<div class="wp-block-codemirror-blocks code-block">
<pre class="CodeMirror" data-setting="{">  module.gke.google_container_cluster.primary
  
<b>-</b> module.gke.google_container_node_pool.pools[0]
<b>+</b> module.gke.google_container_node_pool.pools["default-node-pool"]

  module.vpc.google_compute_network.network
  
<b>-</b> module.vpc.google_compute_subnetwork.subnetwork[0]
<b>+</b> module.vpc.module.subnets.google_compute_subnetwork.subnetwork["southamerica-east1/my-cluster-public"]

<b>-</b> module.vpc.google_compute_subnetwork.subnetwork[1]
<b>+</b> module.vpc.module.subnets.google_compute_subnetwork.subnetwork["southamerica-east1/my-cluster-private"]</pre>
</div>
<h3>3. Importar los nuevos recursos</h3>
<p>Ten en cuenta que la zona/región depende del tipo de clúster. Si es de zona, debe usar la zona maestra (por ejemplo, southamerica-east1-a). Por otro lado, si se trata de un clúster regional, debe usar la región (por ejemplo, southamerica-east1). El siguiente ejemplo supone un clúster regional ubicado en southamerica-east1, en el proyecto «my-project» y con el nombre de clúster «my-cluster». Los nombres de red se configuraron de acuerdo con el nombre del clúster, simplemente agregando los sufijos «private» y «public» a las subredes para diferenciarlos adecuadamente.</p>
<p><strong>Ten en cuenta también la nueva jerarquía de módulos e indexación.</strong></p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{"># Global vars
REGION="southamerica-east1"
PROJECT="my-project"
CLUSTER="my-cluster"

# Cluster
CLUSTER_LOCAL="module.gke.google_container_cluster.primary"
CLUSTER_REMOTE="${PROJECT}/${REGION}/${CLUSTER}"
terraform import $CLUSTER_LOCAL $CLUSTER_REMOTE

# Node pool
POOL_LOCAL="module.gke.google_container_node_pool.pools["default-node-pool"]"
POOL_REMOTE="${CLUSTER_REMOTE}/default-node-pool"
terraform import $POOL_LOCAL $POOL_REMOTE

# Subnetworks
BASE_SUBNET_LOCAL="module.vpc.module.subnets.google_compute_subnetwork.subnetwork"

## Public
PUBLIC_SUBNET_LOCAL="${BASE_SUBNET_LOCAL}["${REGION}/${CLUSTER}-public"]"
PUBLIC_SUBNET_REMOTE="${CLUSTER_REMOTE}-public"
terraform import $PUBLIC_SUBNET_LOCAL $PUBLIC_SUBNET_REMOTE

## Private
PRIVATE_SUBNET_LOCAL="${BASE_SUBNET_LOCAL}["${REGION}/${CLUSTER}-private"]"
PRIVATE_SUBNET_REMOTE="${CLUSTER_REMOTE}-private"
terraform import $PRIVATE_SUBNET_LOCAL $PRIVATE_SUBNET_REMOTE

# Network
NETWORK_LOCAL="module.vpc.module.vpc.google_compute_network.network"
NETWORK_REMOTE="${PROJECT}/${CLUSTER}"
terraform import $NETWORK_LOCAL $NETWORK_REMOTE</pre>
</div>
<h3> 4. Actualizar parámetros</h3>
<p>Es muy probable que encuentres que, después de lanzar un plan de Terraform, el recurso <em><strong>google_container_cluster</strong></em> todavía necesite actualizarse debido a un cambio en el parámetro de subred. Las nuevas claves de subred han hecho que los índices cambien su orden. Simplemente edita el módulo GKE para reemplazar el parámetro <em>subnetwork </em>como se muestra a continuación.</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{"><b>-</b> subnetwork = module.vpc.subnets_names[<b>0</b>]
<b>+</b> subnetwork = module.vpc.subnets_names[<b>1</b>]</pre>
</div>
<h3>Conclusión</h3>
<p>Como habrás visto anteriormente, a veces, al depender de terceros, puede suceder que se introduzca un cambio importante y tengas problemas para recuperar el servicio nuevamente. Además de esto, la solución podría introducir daños colaterales que requerirán subsoluciones adicionales. En este caso particular con respecto a Terraform, lidiar con estados inconsistentes no es realmente común ni recomendado, pero es el único método que tiene disponible para resolverlos en su conjunto de herramientas.</p>
<hr />
<p>Espero que hayas disfrutado de este post y te animo a que <a href="https://geko.cloud/es/blog/">revises nuestro blog para leer otrosposts</a> que puedan ser de tu interés. <a href="https://geko.cloud/es/contacto/">No dudes en contactarnos</a> si deseas que te ayudemos en tus proyectos.</p>
<p>¡Nos vemos en la próxima entrada!</p>
<p>La entrada <a href="https://geko.cloud/es/actualizacion-modulo-terraform-clusteres-publicos-gke/">Actualización del módulo Terraform en los clústeres públicos de GKE</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://geko.cloud/es/actualizacion-modulo-terraform-clusteres-publicos-gke/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Cómo ejecutar Grafana en Docker con Google SSO</title>
		<link>https://geko.cloud/es/como-ejecutar-grafana-en-docker-con-google-sso/</link>
					<comments>https://geko.cloud/es/como-ejecutar-grafana-en-docker-con-google-sso/#respond</comments>
		
		<dc:creator><![CDATA[Xavi Miranda]]></dc:creator>
		<pubDate>Mon, 04 May 2020 13:12:44 +0000</pubDate>
				<category><![CDATA[Labs]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Google Cloud]]></category>
		<category><![CDATA[Grafana]]></category>
		<guid isPermaLink="false">https://geko2.factoryfy.com/?p=1812</guid>

					<description><![CDATA[<p>El objetivo de este laboratorio es aprender cómo configurar la autenticación de SSO de Google en Grafana y también demostrar cuan rápido podemos activar una nueva instancia de Grafana usando el contenedor oficial de docker (no es necesario crear imágenes personalizadas). Si lo que buscas es cómo configurar la autenticación LDAP puedes echar un vistazo a [&#8230;]</p>
<p>La entrada <a href="https://geko.cloud/es/como-ejecutar-grafana-en-docker-con-google-sso/">Cómo ejecutar Grafana en Docker con Google SSO</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>El objetivo de este laboratorio es aprender cómo configurar la <strong>autenticación de SSO de Google</strong> en Grafana y también demostrar cuan rápido podemos activar una nueva instancia de Grafana usando el <strong>contenedor oficial de docker</strong> (no es necesario crear imágenes personalizadas). Si lo que buscas es cómo configurar la <strong>autenticación LDAP</strong> <a href="https://geko.cloud/es/como-instalar-grafana-con-ldap-en-kubernetes-usando-helm/">puedes echar un vistazo a este otro post.</a></p>
<p>En Geko decidimos implementar SSO en la mayoría de nuestros servicios internos, ya que ya trabajamos con cuentas Gsuite, por lo que era el camino obvio. De todos modos, puedes mantener funcional la administración de usuarios predeterminada si aún deseas usarla.</p>
<p>El uso de SSO también nos hace mucho más fácil las nuevas incorporaciones en nuestro equipo, ya que pueden registrarse directamente y solo tenemos que establecer roles para ellos. Incluso para nuestros clientes, y les podemos permitir que sus dominios establezcan cuentas para ellos, si es necesario.</p>
<p><strong>Tiempo estimado para terminar este laboratorio</strong>: 20-30 minutos.</p>
<h3>Setup Google Cloud account</h3>
<p>Para configurar SSO, necesitamos crear algunas credenciales en Google Cloud. Si no tiene un proyecto creado en GCP, deberás crear uno: https://console.cloud.google.com</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-1813" src="https://geko2.factoryfy.com/wp-content/uploads/image1.png" alt="GCP New Project" width="447" height="312" /></p>
<h4>Pantalla de consentimiento Oauth</h4>
<p>La pantalla de consentimiento es lo que los usuarios verán cuando intenten iniciar sesión en su aplicación (Grafana). Puedes usar este enlace para llegar a la configuración: https://console.cloud.google.com/apis/credentials/consent/edit?</p>
<p>Aquí podemos establecer algunos parámetros para personalizar la pantalla de consentimiento. Vamos a establecer los siguientes valores para este laboratorio:</p>
<ul>
<li><strong>Application name</strong>: Grafana</li>
<li><strong>Support email</strong>: Tu correo electrónico o cualquier correo asociado a tu cuenta</li>
<li><strong>Authorized domains</strong>: Estos son los dominios contra los cuales los usuarios podrán autenticarse. Por lo general, se usará el nombre de dominio de la organización, pero es posible que también estés interesado en permitir otros.</li>
</ul>
<p>Como puedes ver, la configuración es bastante sencilla. Si deseas establecer cualquier otro parámetro, siéntete libre, depende de como lo quieras configurar tu.</p>
<h4>Crear credenciales</h4>
<p>Ahora configuraremos las credenciales que se utilizarán en Grafana para autenticarse en nuestro proyecto Google Cloud: https://console.cloud.google.com/apis/credentials?</p>
<ul>
<li>Haz clic en «CREATE CREDENTIALS» y luego en «Oauth Client ID».</li>
<li>Selecciona «Web application», establece el nombre en «Grafana» y haga clic en «Create»</li>
</ul>
<p>A continuación aparece un popup con la información siguiente:</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-1814" src="https://geko2.factoryfy.com/wp-content/uploads/imagen2.png" alt="GCP Oauth2 client created" width="396" height="260" /></p>
<p><strong>Warning!</strong> Guarda tu ID de cliente y el <em>secret client</em> en un lugar seguro.</p>
<h3>Setup Grafana</h3>
<p>Supongo que ya tienes el servicio de configuración docker en tu máquina local. Si no lo has hecho, empieza aquí: https://docs.docker.com/get-docker/</p>
<h4>Persistent volume</h4>
<p>Incluso si usamos Docker querremos tener datos persistentes para que cualquier modificación en la configuración o paneles no se pierda, incluso si eliminamos el contenedor. Esto hace que las actualizaciones a versiones más nuevas sean realmente fáciles y menos dolorosas. Así que adelante y crea un <em>volume</em> para Grafana:</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">docker volume create grafana-data</pre>
</div>
<h4>Prepara los argumentos para configurar Grafana</h4>
<p>Vamos a darle una vuelta al contenedor de Grafana usando algunas variables de entorno para configurar Grafana. Aquí describiremos para qué es cada uno:</p>
<ul>
<li>GF_SECURITY_ADMIN_PASSWORD: Strong random password Contraseña aleatoria segura</li>
<li>GF_SERVER_ROOT_URL:  Configura esto si deseas anular la raíz del servidor. De lo contrario, puedes eliminar este parámetro. Es útil si ejecutas Grafana detrás de un proxy inverso (por ejemplo, nginx) y necesita acceder a una url específica.</li>
<li>GF_AUTH_GOOGLE_ENABLED:  Habilita el SSO de Google</li>
<li>GF_AUTH_GOOGLE_AUTH_URL: Auto explicativo</li>
<li>GF_AUTH_GOOGLE_TOKEN_URL: Auto explicativo</li>
<li>GF_AUTH_GOOGLE_CLIENT_SECRET: Secret client que se obtiene cuando creamos las credenciales en GCP</li>
<li>GF_AUTH_GOOGLE_CLIENT_ID: ID de cliente que se obtiene cuando creamos las credenciales en GCP</li>
<li>GF_ALLOWED_DOMAINS:  El dominio de tu empresa y todos los demás dominios a los que quieres otorgar acceso (por ejemplo, tus clientes)</li>
</ul>
<p>Por supuesto, podemos establecer todos estos parámetros en grafana.ini en lugar de usar variables de entorno, es de tu elección el método que quieres usar.</p>
<h4>Inicia el contenedor Grafana con nuestros argumentos personalizados</h4>
<p>Ahora podemos girar el contenedor. Ten en cuenta que estamos asignando el puerto Grafana a nuestro puerto host 8081:</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">docker run -d --rm -p 8081:3000 --name grafana 
    -e "GF_SECURITY_ADMIN_PASSWORD=&lt;<b>some_password</b>&gt;" 
    -e "GF_SERVER_ROOT_URL=<a href="http://&lt;your_ip&gt;">http://</a>" 
    -e "GF_AUTH_BASIC_ENABLED=&lt;<b>disable_default_auth</b>&gt;" 
    -e "GF_AUTH_GOOGLE_ENABLED=&lt;<b>enable_google_auth</b>&gt;" 
    -e "GF_AUTH_GOOGLE_AUTH_URL=https://accounts.google.com/o/oauth2/auth" 
    -e "GF_AUTH_GOOGLE_TOKEN_URL=https://accounts.google.com/o/oauth2/token" 
    -e "GF_AUTH_GOOGLE_CLIENT_SECRET=&lt;<b>your_client_secret</b>&gt;" 
    -e "GF_AUTH_GOOGLE_CLIENT_ID=&lt;<b>your_client_id</b>&gt;" 
    -e “GF_ALLOWED_DOMAINS=&lt;<b>your_company_domain</b>&gt;”
    -v grafana-storage:/var/lib/grafana 
grafana/grafana</pre>
</div>
<p>Si todo está bien, deberías poder acceder a grafana en http: // localhost: 8081 y ver un botón para autenticarse con Google:</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-1816" src="https://geko2.factoryfy.com/wp-content/uploads/imagen3.png" alt="GrafanaSSO" width="546" height="359" /></p>
<p>&nbsp;</p>
<p>Si intentas iniciar sesión con una cuenta de gmail que pertenece a un dominio permitido, deberías poder acceder a Grafana fácilmente.</p>
<hr />
<p>Espero que hayas disfrutado de este post y te animo a que <a href="https://geko.cloud/es/blog/">revises nuestro blog para leer otrosposts</a> que puedan ser de tu interés, por ejemplo «<a href="https://geko.cloud/es/que-es-kubernetes/">Qué es Kubernetes?</a>«. <a href="https://geko.cloud/es/contacto/">No dudes en contactarnos</a> si deseas que te ayudemos en tus proyectos.</p>
<p>¡Nos vemos en la próxima entrada!</p>
<p>La entrada <a href="https://geko.cloud/es/como-ejecutar-grafana-en-docker-con-google-sso/">Cómo ejecutar Grafana en Docker con Google SSO</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://geko.cloud/es/como-ejecutar-grafana-en-docker-con-google-sso/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Cómo configurar un HAProxy de alta disponibilidad en Google Cloud con Keepalived</title>
		<link>https://geko.cloud/es/configurar-haproxy-googlecloud-keepalived/</link>
					<comments>https://geko.cloud/es/configurar-haproxy-googlecloud-keepalived/#respond</comments>
		
		<dc:creator><![CDATA[Jose Luis Sánchez]]></dc:creator>
		<pubDate>Mon, 02 Mar 2020 08:13:28 +0000</pubDate>
				<category><![CDATA[Labs]]></category>
		<category><![CDATA[Google Cloud]]></category>
		<category><![CDATA[HAproxy]]></category>
		<guid isPermaLink="false">https://geko2.factoryfy.com/?p=910</guid>

					<description><![CDATA[<p>Sí, puedes pensar: «¿Qué? Google Cloud tiene su propio servicio administrado de balanceador de carga. ¿Por qué querría configurar y administrar un load balancer HA dedicado?«. Recomendamos utilizar el servicio GCP Load Balancer siempre que puedas. Es un servicio muy confiable y no tienes que administrar tu propio load balancer en una configuración de alta [&#8230;]</p>
<p>La entrada <a href="https://geko.cloud/es/configurar-haproxy-googlecloud-keepalived/">Cómo configurar un HAProxy de alta disponibilidad en Google Cloud con Keepalived</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Sí, puedes pensar: <em>«¿Qué? Google Cloud tiene su propio servicio administrado de balanceador de carga. ¿Por qué querría configurar y administrar un load balancer HA dedicado?</em>«. Recomendamos utilizar el servicio GCP Load Balancer siempre que puedas. Es un servicio muy confiable y no tienes que administrar tu propio load balancer en una configuración de alta disponibilidad.</p>
<p>Pero a veces hay algunas situaciones en las que GCP Load Balancer no se ajusta a tus necesidades o, simplemente, no deseas usarlo &#8230; En esos casos, tenemos una configuración muy simple utilizando dos piezas de software bien conocidas: <strong>HAProxy </strong>y<strong> Keepalived</strong>.</p>
<p>Keepalived utiliza Virtual Router Redundancy Protocol (<a href="https://tools.ietf.org/html/rfc3768">VRRP</a>) y direcciones IP flotantes que pueden &#8216;moverse&#8217; de una VM a otra en caso de que una de ellas no esté disponible. En un entorno clásico y local, esto es algo así:</p>
<figure id="attachment_912" aria-describedby="caption-attachment-912" style="width: 634px" class="wp-caption aligncenter"><a href="https://geko2.factoryfy.com/wp-content/uploads/floating-ip-on-premises-environment.svg"><img loading="lazy" decoding="async" class="wp-image-912 " src="https://geko2.factoryfy.com/wp-content/uploads/floating-ip-on-premises-environment.svg" alt="" width="634" height="181" /></a><figcaption id="caption-attachment-912" class="wp-caption-text">Image source: Google Cloud</figcaption></figure>
<p>En caso de un server failure, cuando el otro servidor toma las direcciones IP flotantes, agrega estas direcciones a tu interfaz de red. El servidor anuncia esta toma de control a otros dispositivos que utilizan la layer 2 mediante el envío de un marco de <a href="https://en.wikipedia.org/wiki/Address_Resolution_Protocol#ARP_announcements">Protocolo de resolución de direcciones (ARP) gratuito</a>. Google Compute Engine utiliza virtualized network stack y los mecanismos de implementación típicos no funcionan aquí. La red VPC maneja las solicitudes ARP basadas en la topología de enrutamiento configurada e ignora las tramas ARP gratuitas.</p>
<p>En primer lugar, debes instalar haproxy y keepalived en tu servidor. En este caso, usamos <strong>Ubuntu 18.04.</strong> Solo ejecuta:</p>
<pre>sudo apt install haproxy 
sudo apt install keepalived</pre>
<p>Para este tutorial configuraremos un <strong>load balancer interno</strong>, pero también puedes configurar un load balancer externo con algunas pequeñas modificaciones.</p>
<p><img loading="lazy" decoding="async" class="wp-image-945 aligncenter" src="https://geko2.factoryfy.com/wp-content/uploads/screenshot-20200228160149-911x611.png" alt="" width="619" height="415" /></p>
<p>Utilizaremos este archivo /etc/haproxy/haproxy.cfg en ambos servidores. Ambos servidores (MASTER y BACKUP) <strong>deben tener exactamente la misma configuración de HAProxy</strong>.</p>
<pre><span style="font-weight: 400;">global</span>
<span style="font-weight: 400;">        log /dev/log    local0 debug
</span><span style="font-weight: 400;">        log /dev/log    local1 debug</span>
<span style="font-weight: 400;">        chroot /var/lib/haproxy</span>
<span style="font-weight: 400;">        stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners</span>
<span style="font-weight: 400;">        stats timeout 30s</span>
<span style="font-weight: 400;">        user haproxy</span>
<span style="font-weight: 400;">        group haproxy</span>
<span style="font-weight: 400;">        daemon</span>

<span style="font-weight: 400;">defaults</span>
<span style="font-weight: 400;">        log     global</span>
<span style="font-weight: 400;">        mode    http</span>
<span style="font-weight: 400;">        option  dontlognull</span>
<span style="font-weight: 400;">        timeout connect 5000</span>
<span style="font-weight: 400;">        timeout client  50000</span>
<span style="font-weight: 400;">        timeout server  50000</span>
<span style="font-weight: 400;">        errorfile 400 /etc/haproxy/errors/400.http</span>
<span style="font-weight: 400;">        errorfile 403 /etc/haproxy/errors/403.http</span>
<span style="font-weight: 400;">        errorfile 408 /etc/haproxy/errors/408.http</span>
<span style="font-weight: 400;">        errorfile 500 /etc/haproxy/errors/500.http</span>
<span style="font-weight: 400;">        errorfile 502 /etc/haproxy/errors/502.http</span>
<span style="font-weight: 400;">        errorfile 503 /etc/haproxy/errors/503.http</span>
<span style="font-weight: 400;">        errorfile 504 /etc/haproxy/errors/504.http</span>

<span style="font-weight: 400;">frontend service-1</span>
<span style="font-weight: 400;">  bind 192.168.240.140:443</span>
<span style="font-weight: 400;">  mode tcp</span>
<span style="font-weight: 400;">  option tcplog</span>
<span style="font-weight: 400;">  log global</span>
<span style="font-weight: 400;">  default_backend service-1-be</span>
<span style="font-weight: 400;">backend service-1-be</span>
<span style="font-weight: 400;">  mode tcp</span>
<span style="font-weight: 400;">  server service-1-server-1 10.152.0.220:443 check id 1
  server service-1-server-2 10.152.0.221:443 check id 2


</span>frontend service-2
  bind 192.168.240.141:443
  mode tcp
  option tcplog
  log global
  default_backend service-2-be
backend service-2-be
  mode tcp
  server service-2-server-1 10.10.0.40:443 check id 1
  server service-2-server-2 10.10.0.41:443 check id 2</pre>
<p>En este ejemplo, las dos IP flotantes serán: <strong>192.168.240.140</strong> y <strong>192.168.240.141.</strong></p>
<p>No olvides reiniciar el servicio haproxy (sudo systemctl restart haproxy) cada vez que cambies el archivo de configuración. <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Para el archivo de configuración <strong>/etc/keepalived/keepalived.conf</strong> usaremos estos dos archivos de configuración en las VM masters y slaves:</p>
<h3>MASTER</h3>
<pre><span style="font-weight: 400;">vrrp_instance floating_ip {</span>
<span style="font-weight: 400;">    state MASTER</span>
<span style="font-weight: 400;">    interface ens4</span>
<span style="font-weight: 400;">    unicast_src_ip 192.168.240.10</span>
<span style="font-weight: 400;">    unicast_peer {</span>
<span style="font-weight: 400;">        192.168.240.11</span>
<span style="font-weight: 400;">    }</span>

<span style="font-weight: 400;">    virtual_router_id 50</span>
<span style="font-weight: 400;">    priority 100</span>
<span style="font-weight: 400;">    authentication {</span>
<span style="font-weight: 400;">        auth_type PASS</span>
<span style="font-weight: 400;">        auth_pass your_passwd</span>
<span style="font-weight: 400;">    }</span>
<span style="font-weight: 400;">    notify_master /etc/keepalived/takeover.sh root</span>
<span style="font-weight: 400;">}</span></pre>
<h3>BACKUP</h3>
<pre>vrrp_instance floating_ip {
    state BACKUP
    interface ens4
    unicast_src_ip 192.168.240.11
    unicast_peer {
        192.168.240.10
    }

    virtual_router_id 50
    priority 50
    authentication {
        auth_type PASS
        auth_pass your_passwd
    }
    notify_master /etc/keepalived/takeover.sh root
}</pre>
<p>No olvides reiniciar el servicio keepalived (sudo systemctl restart keepalived) cada vez que cambie el archivo de configuración. <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Y ahora la parte que hace la &#8216;magia&#8217;: el script <strong>/etc/keepalived/takeover.sh</strong>. Básicamente, este script desasigna los alias de IP del par que está inactivo y se los asigna a sí mismo. Después de eso, el servicio haproxy se vuelve a cargar para permitir que el haproxy se una a las IP flotantes.</p>
<h3>MASTER</h3>
<pre># Unassign peer's IP aliases. Try it until it's possible.
until gcloud compute instances network-interfaces update haproxy-prod-backup --zone europe-west1-c --aliases "" &gt; /etc/keepalived/takeover.log 2&gt;&amp;1; do
    echo "Instance not accessible during takeover. Retrying in 5 seconds..."
    sleep 5
done

# Assign IP aliases to me because now I am the MASTER!
gcloud compute instances network-interfaces update haproxy-prod 
    --zone europe-west1-b 
    --aliases "192.168.240.140/32;192.168.240.141/32" &gt;&gt; /etc/keepalived/takeover.log 2&gt;&amp;1
systemctl restart haproxy
echo "I became the MASTER at: $(date)" &gt;&gt; /etc/keepalived/takeover.log

</pre>
<h3>BACKUP</h3>
<pre># Unassign peer's IP aliases. Try it until it's possible.
until gcloud compute instances network-interfaces update haproxy-prod --zone europe-west1-b --aliases "" &gt; /etc/keepalived/takeover.log 2&gt;&amp;1; do
    echo "Instance not accessible during takeover. Retrying in 5 seconds..."
    sleep 5
done

# Assign IP aliases to me because now I am the MASTER!
gcloud compute instances network-interfaces update haproxy-prod-backup 
    --zone europe-west1-c 
    --aliases "192.168.240.140/32;192.168.240.141/32" &gt;&gt; /etc/keepalived/takeover.log 2&gt;&amp;1
systemctl restart haproxy
echo "I became the MASTER at: $(date)" &gt;&gt; /etc/keepalived/takeover.log
</pre>
<p>De hecho, todo lo que hacemos es asignar / desasignar alias de IP dependiendo de qué VM sea el MAESTRO.</p>
<p>Fácil, ¿no? <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<hr />
<p>Espero que hayas disfrutado de este post y te animo a que <a href="https://geko.cloud/es/blog/">revises nuestro blog para leer otrosposts</a> que puedan ser de tu interés, por ejemplo «<a href="https://geko.cloud/es/que-es-cloud/">Qué es el cloud?</a>«.</p>
<p>Si tienes alguna duda, <a href="https://geko.cloud/es/contacto/">contáctanos</a> and Feel the Geko Way!</p>
<p>La entrada <a href="https://geko.cloud/es/configurar-haproxy-googlecloud-keepalived/">Cómo configurar un HAProxy de alta disponibilidad en Google Cloud con Keepalived</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://geko.cloud/es/configurar-haproxy-googlecloud-keepalived/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Reenviar IP real a un NGINX detrás de un load balancer GCP</title>
		<link>https://geko.cloud/es/reenviar-ip-real-a-un-nginx-detras-de-un-load-balancer-gcp/</link>
					<comments>https://geko.cloud/es/reenviar-ip-real-a-un-nginx-detras-de-un-load-balancer-gcp/#respond</comments>
		
		<dc:creator><![CDATA[Xavi Miranda]]></dc:creator>
		<pubDate>Fri, 28 Feb 2020 12:26:03 +0000</pubDate>
				<category><![CDATA[Labs]]></category>
		<category><![CDATA[Google Cloud]]></category>
		<category><![CDATA[Ngnix]]></category>
		<guid isPermaLink="false">https://geko2.factoryfy.com/?p=744</guid>

					<description><![CDATA[<p>Este artículo se centra en los load balancer GCP, pero puede aplicarse a otros proveedores cloud / servidores proxy. Introducción En Geko trabajamos en un proyecto que requería un servidor nginx para poder incluir en la lista blanca algunas direcciones IP públicas mientras negaba todas las demás conexiones. Si bien esto puede abordarse utilizando las [&#8230;]</p>
<p>La entrada <a href="https://geko.cloud/es/reenviar-ip-real-a-un-nginx-detras-de-un-load-balancer-gcp/">Reenviar IP real a un NGINX detrás de un load balancer GCP</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p style="text-align: center;"><em>Este artículo se centra en los load balancer GCP, pero puede aplicarse a otros proveedores cloud / servidores proxy.</em></p>
<h2>Introducción</h2>
<p>En <a href="https://geko.cloud/es/">Geko</a> trabajamos en un proyecto que requería un servidor nginx para poder incluir en la lista blanca algunas direcciones IP públicas mientras negaba todas las demás conexiones. Si bien esto puede abordarse utilizando las reglas de firewall de GCP, hubo otras razones por las cuales fue necesario hacerlo a través de la configuración de nginx en lugar de usar las reglas de GCP.</p>
<p><span style="color: #000000;">El problema es que nginx no mostraba la <strong>dirección IP real</strong> correcta de la solicitud en el encabezado <strong>REMOTE_ADDR</strong>.</span></p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">130.211.0.230 - - [23/Jan/2020:09:44:51 +0000] "GET / HTTP/1.1" 404 "108.26.106.168, 36.129.221.25"</pre>
</div>
<h2><span style="color: #000000;"><strong>Escenario</strong></span></h2>
<p>Usaré un escenario muy simple:</p>
<ul>
<li><span style="color: #000000;">Instancia privada de Google Compute que ejecuta dos contenedores docker: nginx y una aplicación basada en php</span></li>
<li>Public GCP Load Balancer dirigido al contenedor nginx.</li>
</ul>
<p>Direcciones IP falsas utilizadas en esta publicación:</p>
<ul>
<li>Solicitudes de origen del usuario: 108.26.106.168</li>
<li>IP pública de GCP Load Balancer: 36.129.221.25</li>
<li>Rango privado de GCP Load Balancer: 130.211.0.0/22 and 35.191.0.0/16</li>
</ul>
<p>Eso es.</p>
<h2>El problema</h2>
<p><span style="color: #000000;">Repasemos rápidamente cómo funciona un load balancer</span><span style="color: #000000;">: cuando se recibe una solicitud de un cliente remoto, se finaliza y se emite una nueva solicitud desde el LB contra el backend, reenviando un conjunto de headers (haz clic en <a href="https://cloud.google.com/load-balancing/docs/https#target-proxies">GCP</a> y <a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html">AWS</a> para obtener detalles específicos) son atrapados por el servicio subyacente.</span></p>
<p><span style="color: #000000;">Cuando colocas un servidor nginx detrás del LB, recibe la IP privada del Load Balancer como dirección remota en lugar de la IP pública real del usuario.</span></p>
<p><span style="color: #000000;"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-828" src="https://geko2.factoryfy.com/wp-content/uploads/travolta-1.gif" alt="" width="426" height="213" /></span></p>
<p>Si echamos un vistazo a los registros de nginx, podemos ver esto:</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">130.211.0.130 - - [23/Jan/2020:09:02:51 +0000] "GET / HTTP/1.1" 200 "108.26.106.168, 36.129.221.25"</pre>
</div>
<p>¡Espera! La dirección IP del usuario aparece en esa cadena al final del registro. ¿Por qué c*j***s está tomando nginx el rango privado de LB como la dirección IP de origen? Bueno, esto se debe a que el LB está haciendo una nueva solicitud.</p>
<h2><span style="color: #000000;"><strong>¿Cómo resolvimos el problema?</strong></span></h2>
<p>La primera IP en el registro proviene del encabezado <strong>REMOTE_ADDR</strong>. Necesitamos reemplazar el valor de este header con la dirección IP real recibida en el header<strong> X-Fordered-For.</strong></p>
<p>Pero hay algo más que debemos tratar con este segundo header: en realidad no solo viene con la IP real del usuario sino también con la dirección pública de Load Balancer.</p>
<p>Para resolver todo esto, utilizaremos el <span style="color: #000000;"><a href="https://nginx.org/en/docs/http/ngx_http_realip_module.html"><strong>real_ip module</strong></a></span>. Vamos a aplicar la siguiente configuración en nginx.conf dentro del bloque «server»:</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">set_real_ip_from 36.129.221.25/32; // LB Public IP address
set_real_ip_from 130.211.0.0/22; // Private IP range for GCP Load Balancers
set_real_ip_from 35.191.0.0/16; //Private IP range for GCP Load Balancers
real_ip_header X-Forwarded-For;
real_ip_recursive on;</pre>
</div>
<p>Vamos a dividirlo:</p>
<ul>
<li><span style="color: #000000;"><strong>set_real_ip_from</strong>: Indicar a nginx que confíe en las IP públicas y privadas de GCP LB.</span></li>
<li><span style="color: #000000;"><strong>real_ip_header</strong>: Reemplaza el encabezado REMOTE_ADDR con los valores de X-Fordered-For.</span></li>
<li><span style="color: #000000;"><strong>real_ip_recursive on</strong>: Filtra las IPs confiables de la cadena, por lo tanto, la última dirección no confiable de la cadena se utilizará como la dirección remota.</span></li>
</ul>
<p>Finalmente pruébalo:</p>
<div class="wp-block-codemirror-blocks code-block ">
<pre class="CodeMirror" data-setting="{">108.26.106.168 - - [23/Jan/2020:09:44:51 +0000] "GET / HTTP/1.1" 200 "108.26.106.168, 36.129.221.25"</pre>
</div>
<h2><strong>Conclusión</strong></h2>
<p>Como podemos ver, la solución fue bastante sencilla, pero aun así llevó un tiempo rebuscar en la documentación para comprender cómo Load Balancer reenviaba los encabezados y cómo podemos ajustar nginx para reescribir los encabezados para lograr el comportamiento esperado.</p>
<p>Sin embargo, fue una buena experiencia de aprendizaje.</p>
<p><span style="color: #000000;">Fuentes: <a href="https://nginx.org/en/docs/http/ngx_http_realip_module.html"><strong>https://nginx.org/en/docs/http/ngx_http_realip_module.html</strong></a></span></p>
<hr />
<p>Espero que hayas disfrutado de este post y te animo a que <a href="https://geko.cloud/es/blog/">revises nuestro blog para leer otros posts</a> que puedan ser de tu interés, por ejemplo «<a href="https://geko.cloud/es/que-es-cloud/">Qué es el cloud?</a>«. <a href="https://geko.cloud/es/contacto/">No dudes en contactarnos</a> si deseas que te ayudemos en tus proyectos.</p>
<p>¡Nos vemos en la próxima entrada!</p>
<p>La entrada <a href="https://geko.cloud/es/reenviar-ip-real-a-un-nginx-detras-de-un-load-balancer-gcp/">Reenviar IP real a un NGINX detrás de un load balancer GCP</a> se publicó primero en <a href="https://geko.cloud/es/">Geko Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://geko.cloud/es/reenviar-ip-real-a-un-nginx-detras-de-un-load-balancer-gcp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
