ansible

速成

yum install ansible -y # 安装
ssh-keygen -t rsa # 生成密钥
ssh-copy-id root@192.168.248.12 # 拷贝密钥
ansible all -m ping # 测试连通性
vi /etc/ansible/hosts # 编辑主机列表

[k8s-node]
192.168.248.12 ansible_ssh_user=root 
192.168.248.13 ansible_ssh_user=root 

ansible k8s-node -m copy -a "src=/etc/kubernetes/admin.conf dest=/etc/kubernetes/admin.conf mode=0644 owner=root group=root" # 拷贝文件

ansible k8s-node -m shell -a "kubectl get nodes" # 执行命令

Ansible目录结构

配置文件目录 /etc/ansible/
配置文件目录 /usr/bin/
Lib库依赖目录 /usr/lib/pythonX.X/site-packages/ansible/
Help文档目录 /usr/share/doc/ansible-X.X.X/
Man文档目录 /usr/share/man/man1/

Ansible Ad-Hoc命令集

命令

ansible all -m ping  # 测试连通性
ansible-inventory --graph  # 展示当前的 inventory(清单)结构
ansible nginx --list  # 列出nginx组所有主机列表信息
ansible web_servers -m systemd -a 'name=nginx state=status'  # 相当于执行systemctl status nginx

参数

❑-v, --verbose:输出更详细的执行过程信息,-vvv可得到执行过程所有信息。
❑-i PATH, --inventory=PATH:指定inventory信息,默认/etc/ansible/hosts。
❑-f NUM, --forks=NUM:并发线程数,默认5个线程。-->通过multiprocessing实现
❑--private-key=PRIVATE_KEY_FILE:指定密钥文件。
❑-m NAME, --module-name=NAME:指定执行使用的模块。
❑-M DIRECTORY, --module-path=DIRECTORY:指定模块存放路径,默认/usr/share/ansible,也可通过ANSIBLE_LIBRARY设定默认路径。
❑-a 'ARGUMENTS', --args='ARGUMENTS':模块参数。
❑-k, --ask-pass SSH:认证密码。
❑-K, --ask-sudo-pass sudo:用户的密码(--sudo时使用)。
❑-o, --one-line:标准输出至一行。
❑-s, --sudo:相当于Linux系统下的sudo命令
❑-t DIRECTORY, --tree=DIRECTORY:输出信息至DIRECTORY目录下,结果文件以远程主机名命名。
❑-T SECONDS, --timeout=SECONDS:指定连接远程主机的最大超时,单位是秒。
❑-B NUM, --background=NUM:后台执行命令,超NUM秒后中止正在执行的任务。
❑-P NUM, --poll=NUM:定期返回后台任务进度。
❑-u USERNAME, --user=USERNAME:指定远程主机以USERNAME运行命令。
❑-U SUDO_USERNAME, --sudo-user=SUDO_USERNAME:使用sudo,相当于Linux下的sudo命令。
❑-c CONNECTION, --connection=CONNECTION:指定连接方式,可用选项paramiko (SSH)、ssh、local, local方式常用于crontab和kickstarts。
❑-l SUBSET, --limit=SUBSET:指定运行主机。
❑-l ~REGEX, --limit=~REGEX:指定运行主机(正则)。
❑--list-hosts:列出符合条件的主机列表,不执行任何命令。

常用模块

  1. debug

debug 模块是 Ansible 内置的调试工具,用于:

  • 输出变量值:通过 var 参数直接打印变量内容。
  • 自定义消息:通过 msg 参数结合 Jinja2 模板输出格式化信息,例如:
debug:
  msg: "当前主机名是 {{ ansible_hostname }}"  # 使用 Jinja2 语法
  1. Shell--在远程主机上执行命令,支持 shell 特性(如管道、变量)。
- name: 执行带管道的命令
  shell: cat /etc/passwd | grep root
  1. Copy-将文件从本地复制到远程主机。
- name: 复制文件
  copy:
    src: /local/path/file.txt
    dest: /remote/path/file.txt
    mode: '0644'  # 设置权限
  1. File
- name: 创建目录
  file:
    path: /remote/dir
    state: directory  # 可选:file、directory、link、absent
    mode: '0755'

- name: 删除文件
  file:
    path: /remote/file.txt
    state: absent
  1. Template --使用 Jinja2 模板生成配置文件并复制到远程主机。
- name: 生成配置文件
  template:
    src: /local/template.j2
    dest: /remote/config.conf
  
template.j2
server_name {{ ansible_hostname }};
port {{ port | default(80) }};
  1. yum/apt--包管理模块(yum 用于 RHEL/CentOS,apt 用于 Debian/Ubuntu)。
- name: 安装Nginx
  yum:
    name: nginx
    state: present  # 可选:present、absent、latest
  1. Service --管理服务(启动、停止、重启等)。
- name: 启动并启用Nginx
  service:
    name: nginx
    state: started
    enabled: yes
  1. User--管理用户账号
- name: 创建用户
  user:
    name: john
    state: present
    password: "{{ 'password' | password_hash('sha512') }}"
    groups: wheel
    shell: /bin/bash
  1. Cron--管理 Cron 任务。
- name: 添加Cron任务
  cron:
    name: "每日备份"
    minute: "0"
    hour: "2"
    job: "/usr/bin/backup.sh"
  1. uri和get_url
- name: 调用API
  uri:
    url: https://api.example.com/data
    method: GET
    return_content: yes


- name: Download Nginx source (idempotent)
  get_url:
    url: https://nginx.org/download/nginx-1.26.1.tar.gz
    dest: /wise/nginx-1.26.1.tar.gz
    mode: '0644'
    checksum: "sha256:{{ lookup('url', 'https://nginx.org/download/nginx-1.26.1.tar.gz.sha256', wantlist=True)[0].split(' ')[0] }}"  # 动态获取校验和
  
1.Ansible 先检查本地文件是否存在。
2.若存在,计算其 SHA256 值并与远程文件的校验和对比。
3,一致则跳过下载,不一致则重新下载。
  1. lineinfile--修改文件中的特定行

lineinfile 默认仅修改最后一个匹配行

- name: 修改配置文件
  lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^PermitRootLogin'
    line: 'PermitRootLogin no'
    state: present

Ansible配置

公钥认证

ssh-keygen  # 生成密钥对
ssh-copy-id root@192.168.137.30  # 传输公钥

配置主机清单

默认的主机清单文件路径:/etc/ansible/hosts[由 /etc/ansible/ansible.cfg 定义] 或 通过 -i 指定自定义文件

  • 示例

    [nginx]
    192.168.248.10 ansible_user=root ansible_password=123456
    192.168.248.20 ansible_user=root ansible_password=123456
    ansible_python_interpreter=/usr/bin/python2.7
    

实战

下载安装包和编译环境

mkdir yaml
vi download.yaml
执行ansible-play download.yaml

- name: 下载基础安装包
- hosts: all
- tasks:
- name: 安装阿里云基础软件源
  get_url:
  url=http://mirrors.aliyun.com/repo/Centos-7.repo
  dest=/etc/yum.repos.d/CentOS-Base.repo
  mode=0644

- name: 创建源码目录
  file:
  path: /wise
  state: directory
  mode: '0755'
- name: 创建rpm目录
  file:
  path: /wise/rpm
  state: directory
  mode: '0755'
- name: 安装编译依赖
  yum:
  name:

  - gcc-c++
  - pcre
  - pcre-devel
  - zlib
  - zlib-devel
  - patch
  - libffi-devel
  - python-devel
  - bzip2-devel
  - openssl-devel
  - ncurses-devel
  - sqlite-devel
  - readline-devel
  - tk-devel
  - gdbm-devel
  - libpcap-devel
  - xz-devel
  - openssl
    state: present
    update_cache: true  # 更新缓存
- name: 下载Nginx源码包
  get_url:
  url: https://nginx.org/download/nginx-1.26.1.tar.gz
  dest: /wise/nginx-1.26.1.tar.gz
  mode: '0644'
- name: 导入 Elasticsearch GPG 密钥
  ansible.builtin.rpm_key:  # 修正模块引用
  key: https://artifacts.elastic.co/GPG-KEY-elasticsearch
  state: present
- name: 创建 Elasticsearch yum 仓库配置文件
  ansible.builtin.copy:
  content: |
  [elastic-8.x]
  name=Elastic repository for 8.x packages
  baseurl=https://artifacts.elastic.co/packages/8.x/yum
  gpgcheck=1
  gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
  enabled=1
  autorefresh=1
  type=rpm-md
  dest: /etc/yum.repos.d/elasticsearch.repo
  mode: '0644'
  owner: root
  group: root
- name: 下载Elasticsearch RPM包
  get_url:
  url: https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.13.4-x86_64.rpm
  dest: /wise/rpm/elasticsearch-8.13.4-x86_64.rpm
  mode: '0644'
  checksum: sha512:https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.13.4-x86_64.rpm.sha512
- name: 下载Kibana RPM包
  get_url:
  url: https://artifacts.elastic.co/downloads/kibana/kibana-8.13.4-x86_64.rpm
  dest: /wise/rpm/kibana-8.13.4-x86_64.rpm
  mode: '0644'
- name: 下载Filebeat RPM包
  get_url:
  url: "https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.13.4-x86_64.rpm"
  dest: "/wise/rpm/filebeat-8.13.4-x86_64.rpm"
  mode: '0644'
  checksum: "sha512:{{ lookup('url', 'https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.13.4-x86_64.rpm.sha512', wantlist=True)[0].split(' ')[0] }}"
  timeout: 300  # 5分钟超时,应对大文件下载
  validate_certs: true  # 验证HTTPS证书

安装Nginx

- name: Deploy Nginx
  hosts: all
  become: yes  # 需要root权限

  tasks:
    - name: 解压Nginx源码包
      unarchive:
        src: /wise/nginx-1.26.1.tar.gz
        dest: /wise
        remote_src: yes
        creates: /wise/nginx-1.26.1/configure

    - name: 配置Nginx编译选项
      shell: |
        ./configure \
        --prefix=/etc/nginx \
        --sbin-path=/usr/sbin/nginx \
        --modules-path=/usr/lib64/nginx/modules \
        --conf-path=/etc/nginx/nginx.conf \
        --http-log-path=/var/log/nginx/access.log \
        --error-log-path=/var/log/nginx/error.log \
        --pid-path=/var/run/nginx.pid \
        --lock-path=/var/run/nginx.lock \
        --with-compat \
        --with-file-aio \
        --with-threads \
        --with-http_v2_module
      args:
        chdir: /wise/nginx-1.26.1
        creates: /wise/nginx-1.26.1/Makefile

    - name: 编译并安装Nginx
      shell: make && make install
      args:
        chdir: /wise/nginx-1.26.1
        creates: /usr/sbin/nginx
  
    - name: 创建Nginx日志目录
      file:
        path: /var/log/nginx
        state: directory
        mode: '0755'
        owner: root
        group: root

    - name: 创建Nginx网页根目录
      file:
        path: /usr/share/nginx/html
        state: directory
        mode: '0755'
        owner: root
        group: root

    - name: 创建conf.d目录
      file:
        path: /etc/nginx/conf.d
        state: directory
        mode: '0755'
        owner: root
        group: root

    - name: 创建默认首页
      copy:
        content: |
          <html>
          <head>
              <title>Welcome to Nginx!</title>
          </head>
          <body>
              <h1>Welcome to Nginx!</h1>
              <p>If you see this page, the nginx web server is successfully installed and
              working. Further configuration is required.</p>
          </body>
          </html>
        dest: /usr/share/nginx/html/index.html
        mode: '0644'
        owner: root
        group: root

    - name: 配置Nginx服务文件
      copy:
        content: |
          [Unit]
          Description=The NGINX HTTP and reverse proxy server
          After=syslog.target network.target remote-fs.target nss-lookup.target

          [Service]
          Type=forking
          PIDFile=/var/run/nginx.pid
          ExecStartPre=/usr/sbin/nginx -t
          ExecStart=/usr/sbin/nginx
          ExecReload=/usr/sbin/nginx -s reload
          ExecStop=/bin/kill -s QUIT $MAINPID
          PrivateTmp=true

          [Install]
          WantedBy=multi-user.target
        dest: /etc/systemd/system/nginx.service
        mode: '0644'
        owner: root
        group: root

    - name: 重载systemd服务
      systemd:
        daemon_reload: yes

    - name: 写入默认的nginx配置
      ansible.builtin.copy:  
        content: |
          server {
              listen       8080;
              server_name  localhost;
              location / {
                  root   /usr/share/nginx/html;
                  index  index.html index.htm;
                  add_header X-Received-XFF $http_x_forwarded_for;
              }
              error_page   500 502 503 504  /50x.html;
              location = /50x.html {
                  root   /usr/share/nginx/html;
              }
          }
        dest: /etc/nginx/conf.d/default.conf
        mode: '0644'
        owner: root
        group: root

    - name: 写入nginx.conf
      ansible.builtin.copy:
        content: |
          worker_processes  auto;
          worker_rlimit_nofile 65535;
          events {
              worker_connections  1024;
          }
          http {
              log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                                '$status $body_bytes_sent "$http_referer" '
                                '"$http_user_agent" "$http_x_forwarded_for"';
              access_log  /var/log/nginx/access.log  main;
              error_log /var/log/nginx/error.log warn;
              sendfile        on;
              keepalive_timeout  65;
              include /etc/nginx/conf.d/*.conf;
          }
        dest: /etc/nginx/nginx.conf
        mode: '0644'
        owner: root
        group: root

    - name: 启动并启用Nginx服务
      systemd:
        name: nginx
        state: started
        enabled: yes

    - name: 验证Nginx服务状态
      command: systemctl is-active nginx
      register: service_status
      failed_when: "'active' not in service_status.stdout"   
ansible all -m shell -a 'systemctl status nginx'

安装ES

---
- name: 安装配置 Elasticsearch 并创建 Ingest Pipeline
  hosts: 192.168.137.30
  become: yes
  gather_facts: yes

  vars:
    es_host: "http://{{ ansible_default_ipv4.address }}:9200"
    pipeline_name: "mynginx"
    pipeline_definition:
      description: "Wise Nginx Access Log"
      processors:
        - grok:
            field: "message"
            patterns:
              - "%{IP:remote_addr} - %{DATA:remote_user} \\[%{HTTPDATE:time_local}\\] \"%{DATA:method} %{DATA:uri} %{DATA:server_protocol}\" %{NUMBER:status_code:long} %{NUMBER:response_bytes:long} \"%{DATA:referer}\" \"%{DATA:user_agent}\" \"%{DATA:x_forwarded_for}\""
        - remove:
            field: "message"

  tasks:
    - name: 安装 Elasticsearch RPM 包
      yum:
        name: /wise/rpm/elasticsearch-8.13.4-x86_64.rpm
        state: present

    - name: 备份原配置文件
      copy:
        src: /etc/elasticsearch/elasticsearch.yml
        dest: /etc/elasticsearch/elasticsearch.yml.bak
        remote_src: yes
        mode: '0644'
      ignore_errors: true  # 首次安装可能不存在原文件

    - name: 写入 Elasticsearch 配置
      copy:
        content: |
          # ---------------------------------- Cluster -----------------------------------
          cluster.name: Ansible_ES
          # ----------------------------------- Paths ------------------------------------
          path.data: /var/lib/elasticsearch
          path.logs: /var/log/elasticsearch
          # ---------------------------------- Network -----------------------------------
          network.host: {{ ansible_default_ipv4.address }}
          http.port: 9200
          transport.port: 9300
          # --------------------------------- Discovery ----------------------------------
          cluster.initial_master_nodes: ["{{ ansible_default_ipv4.address }}"]
          # --------------------------------------------------------------------------------
          xpack.security.enabled: false
          xpack.security.enrollment.enabled: false
          xpack.security.http.ssl.enabled: false
          xpack.security.transport.ssl.enabled: false
        dest: /etc/elasticsearch/elasticsearch.yml
        mode: '0644'
        owner: root
        group: elasticsearch

    - name: 启动并启用 Elasticsearch 服务
      systemd:
        name: elasticsearch
        state: started
        enabled: yes
        daemon_reload: yes

    - name: 等待 Elasticsearch 服务就绪
      wait_for:
        host: "{{ ansible_default_ipv4.address }}"
        port: 9200
        timeout: 60
        delay: 10
      register: es_available
      retries: 3
      until: es_available is succeeded

    - name: 创建 Ingest Pipeline
      uri:
        url: "{{ es_host }}/_ingest/pipeline/{{ pipeline_name }}"
        method: PUT
        body: "{{ pipeline_definition | to_json }}"
        body_format: json
        status_code: 200
        headers:
          Content-Type: "application/json"
      register: pipeline_result
      retries: 3
      delay: 5
      until: pipeline_result.status == 200

    - name: 验证 Pipeline 创建结果
      debug:
        var: pipeline_result.json

安装kibana

---
- name: 配置 Kibana
  hosts: 192.168.137.30
  become: yes  # 添加权限提升,因为需要root权限

  tasks:
    - name: 安装Kibana RPM包
      yum:
        name: /wise/rpm/kibana-8.13.4-x86_64.rpm
        state: present

    - name: 写入Kibana配置
      ansible.builtin.copy:
        content: |
          server.port: 5601
          server.host: {{ ansible_default_ipv4.address }}
          elasticsearch.hosts: ["http://{{ ansible_default_ipv4.address }}:9200"]
          i18n.locale: "zh-CN"  # 添加这一行,设置为中文
        dest: /etc/kibana/kibana.yml
        mode: '0644'

    - name: 启动并启用 kibana 服务
      systemd:
        name: kibana
        state: started
        enabled: yes
        daemon_reload: yes

安装filebeat

---
- name: 配置 Filebeat
  hosts: filebeat

  tasks:
    - name: 安装filebeat RPM包
      yum:
        name: /wise/rpm/filebeat-8.13.4-x86_64.rpm
        state: present

    - name: 写入 filebeat 配置
      ansible.builtin.copy:
        content: |
          logging.level: info

          # 配置日志输出格式(plain 或 json)
          logging.to_files: true
          logging.files:
            path: /var/log/filebeat  # 日志文件路径
            name: filebeat           # 日志文件名前缀
            keepfiles: 7             # 保留的旧日志文件数量
            permissions: 0644        # 日志文件权限
            rotateeverybytes: 104857600  # 日志文件大小限制(100MB)

          # 可选:启用 JSON 格式日志(便于机器解析)
          logging.json: true
          filebeat.inputs:
          - type: log
            id: nginx-access
            paths:
              - /var/log/nginx/access.log
            fields_under_root: true

          processors:
            - drop_fields:
                fields: ["agent.name", "agent.ephemeral_id", "agent.type", "agent.version", "log.offset", "agent.id"]
                ignore_missing: true

          output.elasticsearch:
            hosts: ["192.168.137.30:9200"]
            pipeline: "mynginx"
            indices:
              - index: "nginx-access"
        dest: /etc/filebeat/filebeat.yml
        mode: '0644'
        owner: root
        group: root

    - name: 启动并启用 filebeat 服务
      systemd:
        name: filebeat
        state: started
        enabled: yes
        daemon_reload: yes

image

工作实用

ansible -i host_sudo_list_x86 all -m shell "cp /etc/sudoers /root/sudoers.bak.20250808"
ansible -i host_sudo_list_x86 all -m copy "src=/data/tmp/sudo-1.8.23-10.tl2.3.1_x86_64.tar.gz dest=/tmp/sudo-1.8.23-10.tl2.3.1_x86_64.tar.gz"
ansible -i host_sudo_list_x86 all -m shell "cd /tmp/ && tar xvf sudo-1.8.23-10.tl2.3.1_x86_64.tar.gz"
ansible -i host_sudo_list_x86 all -m shell "rpm -Uvh sudo-1.8.23-10.tl2.3.1.x86_64.rpm"

踩坑

lineinfille和blockinfile

lineinfile

坑一:当使用 insertafter 或 insertbefore 时,如果没找到匹配行,会将新行添加到文件末尾
坑二:当使用 backrefs: yes 时,确实需要同时指定 regexp 参数
坑三:当同时使用 regexp 和 backrefs: yes 时,lineinfile 会执行替换操作而非插入操作;
backrefs: yes + regexp 的组合会触发替换行为

blockinfile

参数 是否必须 说明
path 目标文件路径
block 要插入/替换的文本块
marker 标记文本,用于标识块边界
state present(默认)或 absent(删除)
insertafter 在匹配行后插入
insertbefore 在匹配行前插入

marker: "" 确保不会添加任何注释标记
blockinfile 模块的 insertafter 和 insertbefore 参数是互斥的,不能同时使用

配置实例

--- name: 测试
  hosts: 192.168.137.30
  tasks:
    - name: 在文件末尾插入配置块
      ansible.builtin.blockinfile:
        path: /etc/elasticsearch/elasticsearch.yml
        block: |
          Ending
        marker: ""

    - name: 匹配替换测试  -->测试通过
      ansible.builtin.lineinfile:
        path: /etc/elasticsearch/elasticsearch.yml
        regexp: '^cluster\.name'      # 如果没有匹配行,不会替换
        line: 'cluster.name: Test'
        backrefs: yes                 # 确保只有匹配时才替换

    - name: 不匹配不替换测试  -->测试通过
      ansible.builtin.lineinfile:
        path: /etc/elasticsearch/elasticsearch.yml
        regexp: '^http\.ports'        # 如果没有匹配行,不会替换
        line: 'Error'
        backrefs: yes                 # 确保只有匹配时才替换

    - name: 匹配插入测试
      ansible.builtin.blockinfile:
        path: /etc/elasticsearch/elasticsearch.yml
        block: |
          node.name: ES30
        insertafter: '^cluster\.name'
        marker: ""

排障

现象:
执行
ansible 192.168.248.10 -m command -a "service ntpd status"
收到警告
[WARNING]: Consider using the service module rather than running 'service'.  If you need to use
command because service is insufficient you can add 'warn: false' to this command task or set
'command_warnings=False' in ansible.cfg to get rid of this message.

原因:
1. 推荐使用 Ansible 专门的 service 模块来管理服务。
ansible 192.168.248.10 -m service -a "name=ntpd state=started"

2. 在 ansible.cfg 文件中关闭警告信息
[defaults]
command_warnings = False
现象:
Error reading config file (/etc/ansible/ansible.cfg): File contains no section headers.

原因:
配置文件可能类似这样(缺少 [defaults] 标题)
posted @ 2025-05-26 15:00  WiseHYH  阅读(75)  评论(0)    收藏  举报