Lab Ansible Beginner: descubra Ansible de forma práctica con SSH, Playbooks, Apache y MariaDB

Cuando hablamos de automatización, a menudo nos referimos a ansible. Sin embargo, a primera vista puede parecer complejo de entender, y no siempre es fácil visualizar su utilidad concreta en un entorno informático.

A través de esto primer laboratorio de descubrimiento, Te sugiero que descubras Ansible a través de la práctica, realizando paso a paso varias acciones sencillas y concretas en los servidores Linux.

Aprenderás, en particular, a:

  • configurar una conexión SSH usando claves;
  • crear un inventario de Ansible;
  • comprobar la conectividad de las máquinas;
  • Ejecuta tus primeros libros de jugadas;
  • automatizar las actualizaciones de Debian;
  • implementar Apache;
  • Instalar y configurar MariaDB.

El objetivo de este laboratorio es demostrar que Ansible no es solo para grandes infraestructuras, sino que puede convertirse rápidamente en una herramienta sencilla, potente y muy útil para el uso diario.

Instrucciones de laboratorio

Objetivo

Descubre los fundamentos de Ansible administrando varios servidores Debian desde un servidor de control.

Entorno disponible

Tienes:

  • 1 servidor de control Ansible fue instalado
  • 2 clientes Debian
    • ansible-client1
    • ansible-client2

Información de inicio de sesión

  • Usuario: root
  • Contraseña: formation

lo que lograrás

  1. Generar una clave SSH
  2. Configurar el acceso del cliente
  3. Instala Ansible y crea un inventario YAML.
  4. Prueba la conexión con ansible ping
  5. Crea tu primer manual de jugadas
  6. Actualizar servidores Debian
  7. Instalar Apache en un cliente
  8. Instalar MariaDB en otro cliente.

Consejo

  • Repita los manuales de jugadas varias veces para observar la idempotencia.
  • Tómese el tiempo para leer las reseñas de los pedidos.
  • Comprueba la sintaxis YAML (la indentación es importante).

Recursos


'; }// ── Timer ──────────────────────────────────────────────── function startTimer2(uid, expiresAt) { if (s2[uid] && s2[uid].timerInt) clearInterval(s2[uid].timerInt); var exp = new Date(expiresAt.slice(-1)==='Z' ? expiresAt : expiresAt.replace(' ','T')+'Z').getTime(); var tick = function() { var ms = Math.max(0, exp - Date.now()); var m = Math.floor(ms/60000); var ss = Math.floor((ms%60000)/1000); var txt = (ms<60000?'⚠ ':'↗ ') + m + ':' + ('0'+ss).slice(-2); lbl2(uid, txt, ms<60000?'warn':'active'); if (ms<=0) { clearInterval(s2[uid].timerInt); sessionEnd2(uid); } }; tick(); if (s2[uid]) s2[uid].timerInt = setInterval(tick, 1000); }// ── Fin session ────────────────────────────────────────── function sessionEnd2(uid) { lsDel2(uid); if (s2[uid] && s2[uid].timerInt) clearInterval(s2[uid].timerInt); delete s2[uid]; var wrap = document.querySelector('#' + uid); var lbl = wrap ? wrap.dataset.label || 'Ouvrir le terminal' : 'Ouvrir le terminal'; lbl2(uid, wrap ? wrap.querySelector('.rdp2-lbl').dataset.orig || lbl : lbl, ''); st2(uid, ''); var app = document.getElementById(uid + '-app'); if (app) app.innerHTML = ''; }// ── Stop ───────────────────────────────────────────────── function stop2(uid) { var s = s2[uid]; if (!s) return; st2(uid, 'Arrêt…'); fetch(s.conductor + '/internal/stop', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({session_id: s.sessionId}), credentials:'include' }).finally(function() { if (s.win && !s.win.closed) s.win.close(); sessionEnd2(uid); }); } window.rdp2Stop = function(uid) { stop2(uid); };// ── Liens app ──────────────────────────────────────────── function renderApp2(uid, urlApp, urlAppExtra) { var el = document.getElementById(uid + '-app'); if (!el) return; var h = ''; if (urlApp) h += '🌐 Site'; if (urlAppExtra) h += '🔧 Admin'; h += ''; el.innerHTML = h; }// ── Écrire dans la popup ───────────────────────────────── function writePopup(win, html) { try { win.document.open(); win.document.write(html); win.document.close(); } catch(e) {} }// ── Poll ───────────────────────────────────────────────── function poll2(uid) { var s = s2[uid]; if (!s || !s.win || s.win.closed) { sessionEnd2(uid); return; }fetch(s.conductor + '/internal/session/' + s.sessionId) .then(function(r) { return r.json(); }) .then(function(d) { if (d.status === 'running' && (d.url_terminal || d.url_app)) { // Rediriger la popup vers le terminal var target = d.url_terminal || d.url_app; if (!s.win.closed) s.win.location.href = target;// Boutons app + stop sous le bouton principal renderApp2(uid, d.url_app, d.url_app_extra);// Timer dans le bouton if (d.expires_at) startTimer2(uid, d.expires_at);// Sauvegarder lsSave2(uid, { sessionId: s.sessionId, conductor: s.conductor, urlTerminal: d.url_terminal, urlApp: d.url_app, urlAppExtra: d.url_app_extra, expiresAt: d.expires_at, });} else if (d.status === 'error') { if (!s.win.closed) writePopup(s.win, '' + '' + 'Erreur de démarrage — vous pouvez fermer cette fenêtre.'); st2(uid, 'Erreur'); lsDel2(uid); delete s2[uid]; } else { // Mettre à jour le message dans la popup var statusMsg = d.status === 'launching' ? 'Démarrage du conteneur…' : 'Initialisation…'; try { var el = s.win.document.getElementById('m'); if (el) el.textContent = statusMsg; } catch(e) {} st2(uid, statusMsg); setTimeout(function() { poll2(uid); }, 2000); } }) .catch(function() { setTimeout(function() { poll2(uid); }, 3000); }); }// ── Lancement ──────────────────────────────────────────── function launch2(uid) { var wrap = document.querySelector('#' + uid); if (!wrap) return;// Session active → remettre la popup au premier plan if (s2[uid] && s2[uid].sessionId) { if (s2[uid].win && !s2[uid].win.closed) { s2[uid].win.focus(); return; } // Popup fermée mais session active → réouvrir var saved = lsGet2(uid); if (saved && saved.urlTerminal) { var w2 = openPopup(uid); if (w2) { w2.location.href = saved.urlTerminal; s2[uid].win = w2; } return; } }// ── OUVRIR LA POPUP IMMÉDIATEMENT (action utilisateur directe) ── var win = openPopup(uid); if (!win) { st2(uid, 'Popups bloquées — autorisez ce site puis réessayez'); return; }// Afficher l'écran de chargement dans la popup writePopup(win, loadingHtml('Connexion au serveur…'));var conductor = wrap.dataset.conductor; s2[uid] = { win: win, sessionId: null, conductor: conductor, timerInt: null };var b = wrap.querySelector('.rdp2-btn'); if (b) { b.disabled = true; b.querySelector('.rdp2-lbl').textContent = 'Démarrage…'; }// JWT frais via admin-ajax var fd = new FormData(); fd.append('action', 'rdr_get_jwt'); fd.append('nonce', wrap.dataset.nonce || ''); fetch(window.ajaxurl || '/wp-admin/admin-ajax.php', { method:'POST', body:fd, credentials:'include' }) .then(function(r) { return r.ok ? r.json() : {}; }) .catch(function() { return {}; }) .then(function(jwtData) { if (win.closed) { delete s2[uid]; return; }var body = { stack_slug: wrap.dataset.stack }; var ttl = wrap.dataset.ttl; if (ttl && ttl !== 'null') body.ttl = parseInt(ttl); if (jwtData && jwtData.jwt) body.jwt = jwtData.jwt;// Mettre à jour le message try { var el = win.document.getElementById('m'); if(el) el.textContent = 'Lancement du stack…'; } catch(e){}fetch(conductor + '/lab/launch', { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(body), credentials:'include' }) .then(function(r) { return r.json(); }) .then(function(d) { if (d.error) { writePopup(win, '' + '' + '
' + '
' + d.error + '
' + '
Vous pouvez fermer cette fenêtre
' + ''); st2(uid, d.error); delete s2[uid]; if (b) { b.disabled=false; b.querySelector('.rdp2-lbl').textContent = wrap.querySelector('.rdp2-lbl').dataset.orig || 'Ouvrir'; } return; } s2[uid].sessionId = d.session_id; st2(uid, 'Initialisation…'); poll2(uid); }) .catch(function(e) { st2(uid, 'Erreur réseau'); writePopup(win, 'Erreur réseau'); delete s2[uid]; }); }); }function openPopup(uid) { var wrap = document.querySelector('#' + uid); var w = parseInt(wrap && wrap.dataset.w) || 960; var h = parseInt(wrap && wrap.dataset.h) || 620; var left = Math.round((screen.width - w) / 2); var top = Math.round((screen.height - h) / 2); return window.open('about:blank', uid + '_w2', 'width=' + w + ',height=' + h + ',left=' + left + ',top=' + top + ',menubar=no,toolbar=no,location=no,scrollbars=yes,resizable=yes'); }// ── Reprendre après reload ─────────────────────────────── function tryRestore2(uid) { var saved = lsGet2(uid); if (!saved || !saved.expiresAt) return; var exp = new Date(saved.expiresAt.slice(-1)==='Z' ? saved.expiresAt : saved.expiresAt.replace(' ','T')+'Z').getTime(); if (Date.now() >= exp) { lsDel2(uid); return; }s2[uid] = { win: null, sessionId: saved.sessionId, conductor: saved.conductor, timerInt: null }; renderApp2(uid, saved.urlApp, saved.urlAppExtra); startTimer2(uid, saved.expiresAt); }// ── Init ───────────────────────────────────────────────── document.addEventListener('DOMContentLoaded', function() { document.querySelectorAll('.rdp2-wrap').forEach(function(el) { var lbl = el.querySelector('.rdp2-lbl'); if (lbl) lbl.dataset.orig = lbl.textContent.trim(); tryRestore2(el.id); }); });document.addEventListener('click', function(e) { var b = e.target.closest('.rdp2-btn'); if (b) { launch2(b.dataset.uid); } });})();