MarkTechPost AI模型更新

How to Design an End-to-End Ansible Automation Lab with Playbooks, Inventories, Roles, Vault, Dynamic Inventory, and Custom Modules

2026年5月29日 03:49

重點摘要

In this tutorial, we build a complete Ansible lab that runs end-to-end in Google Colab or any Linux environment. We start by installing ansible-core, setting up a local workspace, creating an Ansible configuration file, and defining both static and dynamic inventories. We then explore key Ansible concepts, including group variables, host variables, variable precedence, ad hoc commands, playbooks, loops, conditionals, registered outputs, facts, templates, custom filters, custom modules, roles, handlers, tags, dry runs, idempotency, and Ansible Vault. Since every host runs locally, we practice these concepts safely without needing SSH keys, remote servers, or cloud infrastructure. Copy CodeCopiedUse a different Browserimport os, sys, subprocess, textwrap, stat BASE = "/content/ansible_lab" i

站內 AI 整理稿

In this tutorial, we build a complete Ansible lab that runs end-to-end in Google Colab or any Linux environment. We start by installing ansible-core, setting up a local workspace, creating an Ansible configuration file, and defining both static and dynamic inventories. We then explore key Ansible concepts, including group variables, host variables, variable precedence, ad hoc commands, playbooks, loops, conditionals, registered outputs, facts, templates, custom filters, custom modules, roles, handlers, tags, dry runs, idempotency, and Ansible Vault. Since every host runs locally, we practice these concepts safely without needing SSH keys, remote servers, or cloud infrastructure. Copy CodeCopiedUse a different Browserimport os, sys, subprocess, textwrap, stat BASE = "/content/ansible_lab" if os.path.isdir("/content") else os.path.expanduser("~/ansible_lab") os.makedirs(BASE, exist_ok=True) ENV = os.environ.copy() ENV["ANSIBLE_CONFIG"] = os.path.join(BASE, "ansible.cfg") ENV["ANSIBLE_FORCE_COLOR"] = "1" ENV["PY_COLORS"] = "0" def banner(title): print("\n" + "=" * 78 + f"\n {title}\n" + "=" * 78) def write(relpath, content): """Write a dedented file under BASE, creating parent dirs.""" path = os.path.join(BASE, relpath) os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, "w") as f: f.write(textwrap.dedent(content).lstrip("\n")) return path def sh(cmd, title=None): """Run a shell command from BASE, stream stdout, never raise.""" if title: banner(title) print(f"$ {cmd}\n") p = subprocess.run(cmd, shell=True, cwd=BASE, env=ENV, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) print(p.stdout) return p.returncode banner("STEP 1 — Installing ansible-core") subprocess.run([sys.executable, "-m", "pip", "install", "-q", "ansible-core"], check=True) sh("ansible --version") write("ansible.cfg", """ [defaults] inventory = ./inventory.ini roles_path = ./roles library = ./library filter_plugins = ./filter_plugins vault_password_file = ./vault_pass.txt host_key_checking = False retry_files_enabled = False interpreter_python = auto_silent callback_result_format = yaml deprecation_warnings = False localhost_warning = False nocows = 1 [privilege_escalation] become = False """) write("inventory.ini", """ [webservers] web1 ansible_connection=local web2 ansible_connection=local [dbservers] db1 ansible_connection=local [datacenter:children] webservers dbservers """) We start by preparing the Ansible workspace, setting environment variables, and defining helper functions that make the tutorial easier to run. We install ansible-core, verify the installation, and create the main Ansible configuration file. We also define a static inventory with local web and database host groups so that we can practice Ansible concepts without using remote servers. Copy CodeCopiedUse a different Browserwrite("group_vars/all.yml", """ --- app_name: "Colab Demo App" app_version: "2.0.1" admin_email: "[email protected]" packages: - nginx - git - htop feature_flags: enable_cache: true enable_metrics: false """) write("host_vars/web1.yml", """ --- server_id: 101 max_connections: 512 """) write("filter_plugins/custom_filters.py", ''' import re def to_slug(value): return re.sub(r"[^a-z0-9]+", "-", str(value).lower()).strip("-") def human_bytes(value): n = float(value) for unit in ["B", "KB", "MB", "GB", "TB"]: if n < 1024: return f"{n:.1f}{unit}" n /= 1024 return f"{n:.1f}PB" class FilterModule(object): def filters(self): return {"to_slug": to_slug, "human_bytes": human_bytes} ''') write("library/system_report.py", ''' #!/usr/bin/python from ansible.module_utils.basic import AnsibleModule import platform, os def main(): module = AnsibleModule( argument_spec=dict( label=dict(type="str", required=True), threshold=dict(type="int", required=False, default=80), ), supports_check_mode=True, ) report = { "label": module.params["label"], "system": platform.system(), "release": platform.release(), "python": platform.python_version(), "cpu_count": os.cpu_count(), "threshold": module.params["threshold"], } module.exit_json(changed=False, report=report, message="Report generated for %s" % module.params["label"]) if __name__ == "__main__": main() ''') We define shared group variables and host-specific variables to show how Ansible manages configuration data and applies variable precedence. We then create a custom Jinja2 filter plugin that converts text into slugs and formats byte values into readable units. We also built a custom Python-based Ansible module that generates a simple system report for each host. Copy CodeCopiedUse a different Browserwrite("roles/webserver/defaults/main.yml", """ --- listen_port: 8080 """) write("roles/webserver/vars/main.yml", """ --- doc_root: "/tmp/www" """) write("roles/webserver/tasks/main.yml", """ --- - name: Ensure docroot exists ansible.builtin.file: path: "{{ doc_root }}" state: directory mode: "0755" - name: Deploy index.html from a Jinja2 template ansible.builtin.template: src: index.html.j2 dest: "{{ doc_root }}/index.html" notify: Restart web service - name: Run handlers immediately (instead of end of play) ansible.builtin.meta: flush_handlers """) write("roles/webserver/handlers/main.yml", """ --- - name: Restart web service ansible.builtin.debug: msg: "(simulated) restarting web service on port {{ listen_port }}" """) write("roles/webserver/templates/index.html.j2", """ <!DOCTYPE html> <html> <head><title>{{ app_name }}</title></head> <body> <h1>{{ app_name }} v{{ app_version }}</h1> <p>Served on port {{ listen_port }} from {{ doc_root }}</p> <p>Host: {{ inventory_hostname }}</p> </body> </html> """) write("templates/report.txt.j2", """ Deployment Report ================= App: {{ app_name }} ({{ app_version }}) Host: {{ inventory_hostname }} Generated: {{ ansible_date_time.iso8601 | default('n/a') }} Slug: {{ app_name | to_slug }} Packages: {% for p in packages %} - {{ p }} {% endfor %} Cache enabled: {{ feature_flags.enable_cache }} Metrics enabled: {{ feature_flags.enable_metrics }} """) dyn = write("dynamic_inventory.py", ''' #!/usr/bin/env python3 import json, sys INV = { "webservers": {"hosts": ["web1", "web2"], "vars": {"role": "frontend"}}, "dbservers": {"hosts": ["db1"], "vars": {"role": "backend"}}, "_meta": { "hostvars": { "web1": {"ansible_connection": "local", "tier": "gold"}, "web2": {"ansible_connection": "local", "tier": "silver"}, "db1": {"ansible_connection": "local", "tier": "gold"}, } }, } if "--host" in sys.argv: print(json.dumps({})) else: print(json.dumps(INV, indent=2)) ''') os.chmod(dyn, os.stat(dyn).st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH) We create a complete web server role with defaults, variables, tasks, handlers, and templates to demonstrate how to build reusable Ansible automation. We use Jinja2 templates to generate an HTML page and a deployment report from Ansible variables. We also add a dynamic inventory script that returns host and group information in JSON format. Copy CodeCopiedUse a different Browserwrite("playbook.yml", """ --- - name: Advanced concepts demo hosts: webservers gather_facts: true vars: deploy_user: colab tasks: - name: Merged variables (group_vars + host_vars precedence) ansible.builtin.debug: msg: "App={{ app_name }} v{{ app_version }} | server_id={{ server_id | default('n/a') }}" - name: CUSTOM filter -> to_slug ansible.builtin.debug: msg: "slug => {{ app_name | to_slug }}" - name: CUSTOM filter -> human_bytes ansible.builtin.debug: msg: "size => {{ 1536000 | human_bytes }}" - name: LOOP with an index variable ansible.builtin.debug: msg: "package #{{ idx + 1 }} = {{ item }}" loop: "{{ packages }}" loop_control: index_var: idx - name: CONDITIONAL (when) — only if caching is enabled ansible.builtin.debug: msg: "cache is ON" when: feature_flags.enable_cache | bool - name: Run a command and REGISTER its output ansible.builtin.command: date +%Y-%m-%d register: date_out changed_when: false - name: SET a derived fact from the registered value ansible.builtin.set_fact: deploy_stam

Related

相關文章

MarkTechPost AI模型更新

Liquid AI Introduces LFM2.5-Embedding-350M and LFM2.5-ColBERT-350M: Dense Bi-Encoder and Late-Interaction Models for Fast Multilingual Search Across 11 Languages

This week, Liquid AI released two new retrieval models. They are LFM2.5-ColBERT-350M and LFM2.5-Embedding-350M. Both hold 350M parameters. Both are the first bidirectional members of the LFM family. They build on LFM2.5-350M-Base, released in March. The pair targets fast multilingual and cross-lingual search across 11 languages. Their footprint is small enough to run almost anywhere. Both are available now on Hugging Face under the LFM Open License v1.0. LFM2.5 Retrievers The two models share one backbone but represent text differently. LFM2.5-Embedding-350M is a dense bi-encoder. It turns each document into a single vector. Pick it when you want the fastest search and the smallest, cheapest index. LFM2.5-ColBERT-350M is a late-interaction model. It converts each token into a vector rather

21 分鐘前
MarkTechPost AI模型更新

Perplexity Launches Brain, a Self-Improving Memory System That Builds a Context Graph of an Agent’s Work and Learns Overnight

Most AI memory remembers the user. It stores your preferences, your tastes, and your role. Perplexity is taking a different path. Today, Perplexity launched Brain, a self-improving memory system for its agent product, Computer. Brain does not focus on remembering you. It remembers what the agent did. That reframes what memory in AI is for. What is Perplexity‘s Brain Brain is a self-improving memory system. It builds a context graph of the work Computer performs. At set intervals, such as overnight, Brain reviews that graph. It then teaches itself how to do the work better. The idea is straightforward. The more work you do, the more efficient Brain makes your Computer. Brain is rolling out today to Perplexity Max and Enterprise Max subscribers in Research Preview. Two Axes of AI Memory Perp

14 小時前

智譜新高,MiniMax承壓,“大模型雙雄”命運殊途

這篇消息聚焦「智譜新高,MiniMax承壓,“大模型雙雄”命運殊途」。原始導語提到:大模型在被市場重新定價 從 AI 情報角度來看,這類內容值得關注其背後的技術進展、產品落地、產業競爭與後續市場影響。

16 小時前