{"id":15942,"date":"2026-04-28T23:20:19","date_gmt":"2026-04-28T15:20:19","guid":{"rendered":"https:\/\/top.duoku.icu\/libs\/15942.html"},"modified":"2026-04-28T23:20:19","modified_gmt":"2026-04-28T15:20:19","slug":"ansible-%e8%87%aa%e5%8a%a8%e5%8c%96%e8%bf%90%e7%bb%b4%ef%bc%9a100-%e5%8f%b0%e6%9c%8d%e5%8a%a1%e5%99%a8%e7%9a%84%e6%89%b9%e9%87%8f%e7%ae%a1%e7%90%86","status":"publish","type":"post","link":"https:\/\/www.srclibs.com\/index.php\/2026\/04\/28\/ansible-%e8%87%aa%e5%8a%a8%e5%8c%96%e8%bf%90%e7%bb%b4%ef%bc%9a100-%e5%8f%b0%e6%9c%8d%e5%8a%a1%e5%99%a8%e7%9a%84%e6%89%b9%e9%87%8f%e7%ae%a1%e7%90%86\/","title":{"rendered":"Ansible \u81ea\u52a8\u5316\u8fd0\u7ef4\uff1a100 \u53f0\u670d\u52a1\u5668\u7684\u6279\u91cf\u7ba1\u7406"},"content":{"rendered":"<div style=\"text-align:center;margin:30px 0;\"><img decoding=\"async\" src=\"https:\/\/top.duoku.icu\/wp-content\/uploads\/2026\/04\/image-98.png\" alt=\"Ansible \u81ea\u52a8\u5316\u8fd0\u7ef4\uff1a100 \u53f0\u670d\u52a1\u5668\u7684\u6279\u91cf\u7ba1\u7406\" style=\"max-width:100%;height:auto;border-radius:12px;box-shadow:0 4px 12px rgba(0,0,0,0.1);\"><\/div>\n<h1>Ansible \u81ea\u52a8\u5316\u8fd0\u7ef4\uff1a100 \u53f0\u670d\u52a1\u5668\u7684\u6279\u91cf\u7ba1\u7406<\/h1>\n<h2>\u5f15\u8a00<\/h2>\n<p>\u5728\u4e91\u8ba1\u7b97\u548c DevOps \u65f6\u4ee3\uff0c\u81ea\u52a8\u5316\u8fd0\u7ef4\u5df2\u6210\u4e3a\u63d0\u5347\u6548\u7387\u7684\u5173\u952e\u3002<strong>Ansible<\/strong> \u4f5c\u4e3a\u4e00\u6b3e\u65e0\u4ee3\u7406\u7684\u81ea\u52a8\u5316\u5de5\u5177\uff0c\u4ee5\u5176\u7b80\u5355\u3001\u5f3a\u5927\u7684\u7279\u6027\uff0c\u6210\u4e3a\u7ba1\u7406\u5927\u89c4\u6a21\u670d\u52a1\u5668\u96c6\u7fa4\u7684\u9996\u9009\u65b9\u6848\u3002<\/p>\n<p><strong>\u4e3a\u4ec0\u4e48\u9009\u62e9 Ansible\uff1f<\/strong><\/p>\n<pre><code>\u274c Shell \u811a\u672c\u7684\u75db\u70b9\uff1a\n<ul>\n<li>\u96be\u4ee5\u7ef4\u62a4\u548c\u6269\u5c55<\/li>\n<li>\u7f3a\u4e4f\u5e42\u7b49\u6027\u4fdd\u8bc1<\/li>\n<li>\u9519\u8bef\u5904\u7406\u590d\u6742<\/li>\n<li>\u72b6\u6001\u8ffd\u8e2a\u56f0\u96be<\/li>\n<\/ul>\n\n\u274c \u4f20\u7edf\u914d\u7f6e\u7ba1\u7406\u5de5\u5177\uff1a\n<ul>\n<li>\u9700\u8981\u5b89\u88c5 Agent\uff08\u5982 Puppet\u3001Chef\uff09<\/li>\n<li>\u5b66\u4e60\u66f2\u7ebf\u9661\u5ced<\/li>\n<li>\u67b6\u6784\u590d\u6742\u5ea6\u9ad8<\/li>\n<\/ul>\n\n\u2705 Ansible \u7684\u4f18\u52bf\uff1a\n<ul>\n<li>\u65e0\u4ee3\u7406\u67b6\u6784\uff0c\u96f6\u989d\u5916\u90e8\u7f72<\/li>\n<li>\u57fa\u4e8e SSH\uff0c\u65e0\u9700\u989d\u5916\u7aef\u53e3<\/li>\n<li>\u7b80\u5355\u6613\u5b66\u7684 YAML \u8bed\u6cd5<\/li>\n<li>\u5f3a\u5927\u7684\u6a21\u5757\u751f\u6001\u7cfb\u7edf\uff082000+ \u6a21\u5757\uff09<\/li>\n<li>\u5b8c\u5168\u5e42\u7b49\u64cd\u4f5c<\/li>\n<\/ul>\n<\/code><\/pre>\n<p><strong>\u9002\u7528\u573a\u666f\uff1a<\/strong><\/p>\n<ul>\n<li>? \u670d\u52a1\u5668\u6279\u91cf\u914d\u7f6e\u7ba1\u7406<\/li>\n<li>? \u5e94\u7528\u6279\u91cf\u90e8\u7f72<\/li>\n<li>? \u6279\u91cf\u5347\u7ea7\u548c\u8865\u4e01\u7ba1\u7406<\/li>\n<li>? \u5408\u89c4\u6027\u68c0\u67e5\u548c\u5ba1\u8ba1<\/li>\n<li>? \u65e5\u5e38\u8fd0\u7ef4\u81ea\u52a8\u5316<\/li>\n<\/ul>\n<p><strong>\u9002\u7528\u8bfb\u8005\uff1a<\/strong> \u7cfb\u7edf\u8fd0\u7ef4\u5de5\u7a0b\u5e08\u3001DevOps \u5de5\u7a0b\u5e08\u3001IT \u7ba1\u7406\u5458<\/p>\n<p>&#8212;<\/p>\n<h2>Ansible \u6838\u5fc3\u6982\u5ff5<\/h2>\n<h3>1. \u6838\u5fc3\u7ec4\u4ef6<\/h3>\n<pre><code>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                   Ansible \u6838\u5fc3\u6982\u5ff5                          \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502                                                             \u2502\n\u2502  Inventory (\u6e05\u5355)                                          \u2502\n\u2502  \u2514\u2500 \u5b9a\u4e49\u8981\u7ba1\u7406\u7684\u4e3b\u673a\u5217\u8868\u548c\u5206\u7ec4                              \u2502\n\u2502      \u2502                                                      \u2502\n\u2502      \u251c\u2500 Modules (\u6a21\u5757)                                      \u2502\n\u2502      \u2502   \u2514\u2500 \u5177\u4f53\u64cd\u4f5c\u5355\u5143\uff08\u5982 copy\u3001file\u3001service \u7b49\uff09        \u2502\n\u2502      \u2502                                                             \u2502\n\u2502      \u251c\u2500 Playbooks (\u5267\u672c)                                    \u2502\n\u2502      \u2502   \u2514\u2500 YAML \u6587\u4ef6\uff0c\u5b9a\u4e49\u6267\u884c\u4efb\u52a1\u5e8f\u5217                       \u2502\n\u2502      \u2502                                                             \u2502\n\u2502      \u2514\u2500 Roles (\u89d2\u8272)                                        \u2502\n\u2502          \u2514\u2500 \u53ef\u590d\u7528\u7684\u4efb\u52a1\u96c6\u5408                                 \u2502\n\u2502                                                             \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n<\/code><\/pre>\n<h3>2. Inventory \u914d\u7f6e<\/h3>\n<pre><code># hosts - \u4e3b\u673a\u6e05\u5355\n[webservers]\nweb01 ansible_host=192.168.1.10\nweb02 ansible_host=192.168.1.11\nweb03 ansible_host=192.168.1.12\n\n[database]\ndb01 ansible_host=192.168.1.20\ndb02 ansible_host=192.168.1.21\n\n[all:vars]\nansible_user=ops\nansible_port=22\nansible_python_interpreter=\/usr\/bin\/python3\n\n[webservers:vars]\nhttp_port=80\nmax_clients=200\n<\/code><\/pre>\n<h3>3. Inventory \u5206\u7ec4\u7ed3\u6784<\/h3>\n<pre><code># \u591a\u5c42\u7ea7\u5206\u7ec4\n[all:children]\nwebservers\ndbservers\nappservers\n\n[webservers]\nweb01\nweb02\nweb03\n\n[appservers]\napp01\napp02\n<\/code><\/pre>\n<p>&#8212;<\/p>\n<h2>\u5b89\u88c5\u4e0e\u914d\u7f6e<\/h2>\n<h3>1. \u5b89\u88c5 Ansible<\/h3>\n<pre><code># CentOS\/RHEL\nsudo yum install epel-release\nsudo yum install ansible\n\n<h1>Ubuntu\/Debian<\/h1>\nsudo apt update\nsudo apt install ansible\n\n<h1>\u4f7f\u7528 pip \u5b89\u88c5\u6700\u65b0\u7248\u672c<\/h1>\npip install ansible\n\n<h1>\u9a8c\u8bc1\u5b89\u88c5<\/h1>\nansible --version\nansible-config list\n<\/code><\/pre>\n<h3>2. SSH \u5bc6\u94a5\u914d\u7f6e<\/h3>\n<pre><code># \u751f\u6210 SSH \u5bc6\u94a5\nssh-keygen -t ed25519 -C \"ops@ansible\"\n\n<h1>\u5206\u53d1\u516c\u94a5\u5230\u6240\u6709\u4e3b\u673a<\/h1>\nfor host in web01 web02 web03 db01 db02; do\n    ssh-copy-id ops@$host\ndone\n\n<h1>\u6216\u8005\u4f7f\u7528\u6279\u91cf\u5206\u53d1<\/h1>\nansible all -m copy -a \"src=\/root\/.ssh\/id_ed25519.pub dest=~\/.ssh\/authorized_keys\"\n<\/code><\/pre>\n<h3>3. \u914d\u7f6e\u6587\u4ef6<\/h3>\n<p>&#8220;`yaml<\/p>\n<h1>ansible.cfg \u914d\u7f6e\u793a\u4f8b<\/h1>\n<p>[defaults]<br \/>\ninventory = .\/hosts<br \/>\nhost_key_checking = False<br \/>\nremote_user = ops<br \/>\ntimeout = 30<br \/>\nforks = 50<br \/>\nretry_files_enabled = False<br \/>\nstdout_callback = yaml<br \/>\nroles_path = .\/roles<\/p>\n<p>[inventory]<br \/>\nenable_plugins = host_list, script, yaml, ini<\/p>\n<p>[privilege_escalation]<br \/>\nbecome = True<br \/>\nbecome_method = sudo<br \/>\nbecome_user = root<br \/>\nbecome_ask_pass = False<\/p>\n<pre><code>\n---\n\n<h2>\u6279\u91cf\u7ba1\u7406<\/h2>\n\n<h3>1. \u4e3b\u673a\u5206\u7ec4\u7ba1\u7406<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>\u6309\u73af\u5883\u5206\u7ec4<\/h1>\n<p>[production]<br \/>\nweb01 ansible_host=10.0.1.10<br \/>\nweb02 ansible_host=10.0.1.11<br \/>\nweb03 ansible_host=10.0.1.12<\/p>\n<p>[staging]<br \/>\nweb04 ansible_host=10.0.2.10<br \/>\nweb05 ansible_host=10.0.2.11<\/p>\n<p>[production:children]<br \/>\nwebservers<br \/>\nloadbalancers<\/p>\n<pre><code>\n<h3>2. \u53d8\u91cf\u5b9a\u4e49<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>group_vars\/webservers.yml<\/h1>\n<p>http_port: 80<br \/>\nmax_connections: 200<br \/>\nssl_enabled: true<br \/>\nssl_certificate: \/etc\/ssl\/nginx.crt<br \/>\nssl_key: \/etc\/ssl\/nginx.key<\/p>\n<h1>host_vars\/web01.yml<\/h1>\n<p>nginx_worker_processes: 4<br \/>\nnginx_cache_size: 500m<\/p>\n<pre><code>\n<h3>3. \u6a21\u677f\u914d\u7f6e<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>templates\/nginx.conf.j2<\/h1>\n<p>server {<br \/>\n    listen {{ http_port }};<br \/>\n    server_name {{ ansible_fqdn }};<\/p>\n<p>    worker_processes {{ nginx_worker_processes | default(2) }};<\/p>\n<p>    location \/ {<br \/>\n        proxy_pass http:\/\/localhost:{{ application_port | default(3000) }};<br \/>\n        proxy_set_header Host $host;<br \/>\n        proxy_set_header X-Real-IP $remote_addr;<br \/>\n    }<\/p>\n<p>    {% if ssl_enabled %}<br \/>\n    ssl_certificate {{ ssl_certificate }};<br \/>\n    ssl_key {{ ssl_key }};<br \/>\n    {% endif %}<br \/>\n}<\/p>\n<pre><code>\n---\n\n<h2>\u6279\u91cf\u4efb\u52a1<\/h2>\n\n<h3>1. \u6279\u91cf\u6267\u884c\u547d\u4ee4<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>\u6267\u884c\u5355\u6761\u547d\u4ee4<\/h1>\n<p>ansible all -m command -a &#8220;uptime&#8221;<br \/>\nansible webservers -m shell -a &#8220;df -h&#8221;<\/p>\n<h1>\u4f7f\u7528\u6a21\u5757\u6267\u884c<\/h1>\n<p>ansible all -m ping<br \/>\nansible webservers -m copy -a &#8220;src=file.txt dest=\/tmp\/&#8221;<\/p>\n<pre><code>\n<h3>2. \u6279\u91cf\u914d\u7f6e\u6587\u4ef6<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>playbook.yml<\/h1>\n<ul>\n<li>name: \u914d\u7f6e Nginx<\/li>\n<\/ul>\n<p>  hosts: webservers<br \/>\n  become: yes<br \/>\n  vars:<br \/>\n    http_port: 80<\/p>\n<p>  tasks:<\/p>\n<ul>\n<li>name: \u5b89\u88c5 Nginx<\/li>\n<\/ul>\n<p>      apt:<br \/>\n        name: nginx<br \/>\n        state: present<br \/>\n      when: ansible_os_family == &#8220;Debian&#8221;<\/p>\n<ul>\n<li>name: \u590d\u5236\u914d\u7f6e\u6587\u4ef6<\/li>\n<\/ul>\n<p>      template:<br \/>\n        src: templates\/nginx.conf.j2<br \/>\n        dest: \/etc\/nginx\/nginx.conf<br \/>\n        mode: &#8216;0644&#8217;<br \/>\n      notify: restart nginx<\/p>\n<ul>\n<li>name: \u542f\u52a8 Nginx<\/li>\n<\/ul>\n<p>      service:<br \/>\n        name: nginx<br \/>\n        state: started<br \/>\n        enabled: yes<\/p>\n<p>  handlers:<\/p>\n<ul>\n<li>name: restart nginx<\/li>\n<\/ul>\n<p>      service:<br \/>\n        name: nginx<br \/>\n        state: restarted<\/p>\n<pre><code>\n<h3>3. \u6279\u91cf\u8f6f\u4ef6\u5b89\u88c5<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<ul>\n<li>name: \u6279\u91cf\u5b89\u88c5\u5e38\u7528\u8f6f\u4ef6<\/li>\n<\/ul>\n<p>  hosts: all<br \/>\n  become: yes<br \/>\n  vars:<br \/>\n    packages:<\/p>\n<ul>\n<li>vim<\/li>\n<li>htop<\/li>\n<li>net-tools<\/li>\n<li>git<\/li>\n<li>curl<\/li>\n<\/ul>\n<p>  tasks:<\/p>\n<ul>\n<li>name: \u5b89\u88c5\u8f6f\u4ef6\u5305<\/li>\n<\/ul>\n<p>      package:<br \/>\n        name: &#8220;{{ packages }}&#8221;<br \/>\n        state: present<\/p>\n<ul>\n<li>name: \u9a8c\u8bc1\u5b89\u88c5<\/li>\n<\/ul>\n<p>      command: &#8220;{{ item }} &#8211;version&#8221;<br \/>\n      register: version_output<br \/>\n      loop: &#8220;{{ packages }}&#8221;<br \/>\n      failed_when: false<\/p>\n<ul>\n<li>name: \u663e\u793a\u7248\u672c\u4fe1\u606f<\/li>\n<\/ul>\n<p>      debug:<br \/>\n        var: version_output.stdout<\/p>\n<pre><code>\n---\n\n<h2>\u5b89\u5168\u7ba1\u7406<\/h2>\n\n<h3>1. SSH \u5bc6\u94a5\u7ba1\u7406<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>\u4f7f\u7528 SSH \u5bc6\u94a5\u8ba4\u8bc1<\/h1>\n<ul>\n<li>name: \u4f7f\u7528 SSH \u5bc6\u94a5<\/li>\n<\/ul>\n<p>  hosts: webservers<br \/>\n  connection: ssh<br \/>\n  user: ops<br \/>\n  private_key_file: ~\/.ssh\/id_ed25519<br \/>\n  become: yes<br \/>\n  become_user: root<\/p>\n<pre><code>\n<h3>2. Vault \u52a0\u5bc6<\/h3>\n\n<\/code><\/pre>\n<p>bash<\/p>\n<h1>\u521b\u5efa\u52a0\u5bc6\u6587\u4ef6<\/h1>\n<p>ansible-vault create secrets.yml<\/p>\n<h1>\u7f16\u8f91\u52a0\u5bc6\u6587\u4ef6<\/h1>\n<p>ansible-vault edit secrets.yml<\/p>\n<h1>\u8fd0\u884c\u52a0\u5bc6 Playbook<\/h1>\n<p>ansible-playbook playbook.yml &#8211;ask-vault-pass<\/p>\n<h1>\u4f7f\u7528\u5bc6\u7801\u6587\u4ef6<\/h1>\n<p>ansible-playbook playbook.yml &#8211;vault-password-file=.vault_pass<\/p>\n<pre><code>\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>secrets.yml (\u52a0\u5bc6\u5185\u5bb9)<\/h1>\n<p>db_password: &#8220;s3cur3p@ssw0rd&#8221;<br \/>\napi_key: &#8220;sk-1234567890abcdef&#8221;<br \/>\njwt_secret: &#8220;your-jwt-secret-here&#8221;<\/p>\n<pre><code>\n<h3>3. \u6743\u9650\u63a7\u5236<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>playbook.yml \u6743\u9650\u63a7\u5236<\/h1>\n<ul>\n<li>name: \u53d7\u9650\u7ba1\u7406<\/li>\n<\/ul>\n<p>  hosts: webservers<br \/>\n  become: yes<br \/>\n  vars_files:<\/p>\n<ul>\n<li>secrets.yml<\/li>\n<\/ul>\n<p>  tasks:<\/p>\n<ul>\n<li>name: \u53ea\u8bfb\u64cd\u4f5c\uff08\u65e0\u9700\u7279\u6743\uff09<\/li>\n<\/ul>\n<p>      ansible.builtin.shell: cat \/etc\/hostname<br \/>\n      changed_when: false<br \/>\n      check_mode: yes<\/p>\n<ul>\n<li>name: \u7cfb\u7edf\u914d\u7f6e\uff08\u9700\u8981\u7279\u6743\uff09<\/li>\n<\/ul>\n<p>      ansible.builtin.copy:<br \/>\n        content: &#8220;privileged content&#8221;<br \/>\n        dest: \/etc\/privileged.conf<br \/>\n        mode: &#8216;0600&#8217;<br \/>\n      become: yes<\/p>\n<pre><code>\n---\n\n<h2>\u5b9e\u6218\u6848\u4f8b<\/h2>\n\n<h3>1. Web \u670d\u52a1\u5668\u6279\u91cf\u90e8\u7f72<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<ul>\n<li>name: Web \u670d\u52a1\u5668\u6279\u91cf\u90e8\u7f72<\/li>\n<\/ul>\n<p>  hosts: webservers<br \/>\n  become: yes<br \/>\n  gather_facts: yes<\/p>\n<p>  vars:<br \/>\n    app_user: www-data<br \/>\n    app_group: www-data<br \/>\n    app_dir: \/var\/www\/myapp<\/p>\n<p>  tasks:<\/p>\n<ul>\n<li>name: \u5b89\u88c5\u4f9d\u8d56\u5305<\/li>\n<\/ul>\n<p>      apt:<br \/>\n        name:<\/p>\n<ul>\n<li>nginx<\/li>\n<li>python3<\/li>\n<li>python3-pip<\/li>\n<li>build-essential<\/li>\n<\/ul>\n<p>        state: present<\/p>\n<ul>\n<li>name: \u521b\u5efa\u5e94\u7528\u7528\u6237<\/li>\n<\/ul>\n<p>      user:<br \/>\n        name: &#8220;{{ app_user }}&#8221;<br \/>\n        group: &#8220;{{ app_group }}&#8221;<br \/>\n        shell: \/bin\/bash<br \/>\n        create_home: no<\/p>\n<ul>\n<li>name: \u521b\u5efa\u5e94\u7528\u76ee\u5f55<\/li>\n<\/ul>\n<p>      file:<br \/>\n        path: &#8220;{{ app_dir }}&#8221;<br \/>\n        state: directory<br \/>\n        owner: &#8220;{{ app_user }}&#8221;<br \/>\n        group: &#8220;{{ app_group }}&#8221;<br \/>\n        mode: &#8216;0755&#8217;<\/p>\n<ul>\n<li>name: \u90e8\u7f72\u5e94\u7528\u4ee3\u7801<\/li>\n<\/ul>\n<p>      synchronize:<br \/>\n        src: .\/app\/<br \/>\n        dest: &#8220;{{ app_dir }}\/&#8221;<br \/>\n        owner: &#8220;{{ app_user }}&#8221;<br \/>\n        group: &#8220;{{ app_group }}&#8221;<br \/>\n        archive: true<\/p>\n<ul>\n<li>name: \u914d\u7f6e Nginx<\/li>\n<\/ul>\n<p>      template:<br \/>\n        src: templates\/nginx.conf.j2<br \/>\n        dest: \/etc\/nginx\/nginx.conf<br \/>\n        owner: root<br \/>\n        group: root<br \/>\n        mode: &#8216;0644&#8217;<br \/>\n      notify: restart nginx<\/p>\n<ul>\n<li>name: \u6d4b\u8bd5 Nginx \u914d\u7f6e<\/li>\n<\/ul>\n<p>      command: nginx -t<br \/>\n      changed_when: false<\/p>\n<ul>\n<li>name: \u542f\u7528\u7f51\u7ad9<\/li>\n<\/ul>\n<p>      command: ln -s \/etc\/nginx\/sites-available\/default \/etc\/nginx\/sites-enabled\/<br \/>\n      args:<br \/>\n        creates: \/etc\/nginx\/sites-enabled\/default<\/p>\n<p>  handlers:<\/p>\n<ul>\n<li>name: restart nginx<\/li>\n<\/ul>\n<p>      service:<br \/>\n        name: nginx<br \/>\n        state: restarted<br \/>\n        daemon_reload: yes<\/p>\n<pre><code>\n<h3>2. \u6570\u636e\u5e93\u670d\u52a1\u5668\u6279\u91cf\u914d\u7f6e<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<ul>\n<li>name: \u6570\u636e\u5e93\u670d\u52a1\u5668\u914d\u7f6e<\/li>\n<\/ul>\n<p>  hosts: database<br \/>\n  become: yes<\/p>\n<p>  vars:<br \/>\n    mysql_root_password: &#8220;{{ vault_mysql_root_password }}&#8221;<br \/>\n    mysql_datadir: \/var\/lib\/mysql<br \/>\n    mysql_bind_address: 127.0.0.1<\/p>\n<p>  tasks:<\/p>\n<ul>\n<li>name: \u5b89\u88c5 MySQL<\/li>\n<\/ul>\n<p>      apt:<br \/>\n        name:<\/p>\n<ul>\n<li>mysql-server<\/li>\n<li>mysql-client<\/li>\n<li>python3-mysqldb<\/li>\n<\/ul>\n<p>        state: present<\/p>\n<ul>\n<li>name: \u914d\u7f6e MySQL<\/li>\n<\/ul>\n<p>      template:<br \/>\n        src: templates\/mysql.cnf.j2<br \/>\n        dest: \/etc\/mysql\/mysql.conf.d\/server.cnf<br \/>\n        owner: root<br \/>\n        group: root<br \/>\n        mode: &#8216;0644&#8217;<br \/>\n      notify: restart mysql<\/p>\n<ul>\n<li>name: \u8bbe\u7f6e root \u5bc6\u7801<\/li>\n<\/ul>\n<p>      mysql_user:<br \/>\n        name: root<br \/>\n        host: localhost<br \/>\n        password: &#8220;{{ mysql_root_password }}&#8221;<br \/>\n      when: ansible_os_family == &#8220;Debian&#8221;<\/p>\n<ul>\n<li>name: \u521b\u5efa\u6570\u636e\u5e93<\/li>\n<\/ul>\n<p>      mysql_db:<br \/>\n        name: &#8220;{{ item }}&#8221;<br \/>\n        state: present<br \/>\n        collation: utf8_general_ci<br \/>\n        encoding: utf8<br \/>\n      loop:<\/p>\n<ul>\n<li>production_db<\/li>\n<li>staging_db<\/li>\n<\/ul>\n<ul>\n<li>name: \u521b\u5efa\u5e94\u7528\u7528\u6237<\/li>\n<\/ul>\n<p>      mysql_user:<br \/>\n        name: &#8220;{{ item.user }}&#8221;<br \/>\n        password: &#8220;{{ item.password }}&#8221;<br \/>\n        priv: &#8220;*.*:ALL&#8221;<br \/>\n        host: &#8220;%&#8221;<br \/>\n        state: present<br \/>\n      loop:<\/p>\n<ul>\n<li>{ user: &#8216;app_user&#8217;, password: &#8220;{{ vault_app_password }}&#8221; }<\/li>\n<li>{ user: &#8216;readonly_user&#8217;, password: &#8220;{{ vault_readonly_password }}&#8221; }<\/li>\n<\/ul>\n<p>  handlers:<\/p>\n<ul>\n<li>name: restart mysql<\/li>\n<\/ul>\n<p>      service:<br \/>\n        name: mysql<br \/>\n        state: restarted<\/p>\n<pre><code>\n---\n\n<h2>\u6700\u4f73\u5b9e\u8df5<\/h2>\n\n<h3>1. Playbook \u7ec4\u7ec7<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>project\/<\/h1>\n<h1>\u251c\u2500\u2500 ansible.cfg<\/h1>\n<h1>\u251c\u2500\u2500 inventory\/<\/h1>\n<h1>\u2502   \u251c\u2500\u2500 hosts<\/h1>\n<h1>\u2502   \u251c\u2500\u2500 group_vars\/<\/h1>\n<h1>\u2502   \u2502   \u251c\u2500\u2500 all.yml<\/h1>\n<h1>\u2502 \u2502   \u2502   \u2514\u2500\u2500 webservers.yml<\/h1>\n<h1>\u2502 \u2514\u2500\u2500 host_vars\/<\/h1>\n<h1>\u2502     \u2514\u2500\u2500 web01.yml<\/h1>\n<h1>\u251c\u2500\u2500 playbooks\/<\/h1>\n<h1>\u2502   \u251c\u2500\u2500 deploy.yml<\/h1>\n<h1>\u2502   \u251c\u2500\u2500 upgrade.yml<\/h1>\n<h1>\u2502   \u2514\u2500\u2500 cleanup.yml<\/h1>\n<h1>\u251c\u2500\u2500 roles\/<\/h1>\n<h1>\u2502   \u251c\u2500\u2500 nginx\/<\/h1>\n<h1>\u2502   \u2502   \u251c\u2500\u2500 tasks\/<\/h1>\n<h1>\u2502   \u2502   \u251c\u2500\u2500 handlers\/<\/h1>\n<h1>\u2502   \u2502   \u251c\u2500\u2500 templates\/<\/h1>\n<h1>\u2502   \u2502   \u251c\u2500\u2500 vars\/<\/h1>\n<h1>\u2502   \u2502   \u2514\u2500\u2500 defaults\/<\/h1>\n<h1>\u2502   \u2514\u2500\u2500 mysql\/<\/h1>\n<h1>\u2514\u2500\u2500 vault\/<\/h1>\n<h1>\u2514\u2500\u2500 secrets.yml<\/h1>\n<pre><code>\n<h3>2. CI\/CD \u96c6\u6210<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>.github\/workflows\/ansible.yml<\/h1>\n<p>name: Ansible CI<\/p>\n<p>on:<br \/>\n  push:<br \/>\n    paths:<\/p>\n<ul>\n<li>&#8216;ansible\/**&#8217;<\/li>\n<\/ul>\n<p>  pull_request:<br \/>\n    paths:<\/p>\n<ul>\n<li>&#8216;ansible\/**&#8217;<\/li>\n<\/ul>\n<p>jobs:<br \/>\n  validate:<br \/>\n    runs-on: ubuntu-latest<br \/>\n    steps:<\/p>\n<ul>\n<li>uses: actions\/checkout@v3<\/li>\n<\/ul>\n<ul>\n<li>name: Install Ansible<\/li>\n<\/ul>\n<p>        run: pip install ansible-lint ansible-vault<\/p>\n<ul>\n<li>name: Lint Playbooks<\/li>\n<\/ul>\n<p>        run: ansible-lint playbooks\/<\/p>\n<ul>\n<li>name: Syntax Check<\/li>\n<\/ul>\n<p>        run: ansible-playbook playbooks\/*.yml &#8211;syntax-check<\/p>\n<ul>\n<li>name: Check Vault Files<\/li>\n<\/ul>\n<p>        run: ansible-vault view vault\/secrets.yml<\/p>\n<pre><code>\n<h3>3. \u9519\u8bef\u5904\u7406<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<ul>\n<li>name: \u9519\u8bef\u5904\u7406\u793a\u4f8b<\/li>\n<\/ul>\n<p>  hosts: all<br \/>\n  tasks:<\/p>\n<ul>\n<li>name: \u6267\u884c\u53ef\u80fd\u5931\u8d25\u7684\u64cd\u4f5c<\/li>\n<\/ul>\n<p>      shell: risky_command<br \/>\n      ignore_errors: yes<br \/>\n      register: result<\/p>\n<ul>\n<li>name: \u68c0\u67e5\u9519\u8bef<\/li>\n<\/ul>\n<p>      fail:<br \/>\n        msg: &#8220;\u64cd\u4f5c\u5931\u8d25: {{ result.msg }}&#8221;<br \/>\n      when: result.failed<\/p>\n<ul>\n<li>name: \u6267\u884c\u91cd\u8bd5\u903b\u8f91<\/li>\n<\/ul>\n<p>      shell: recovery_command<br \/>\n      when: result.failed<\/p>\n<ul>\n<li>name: \u8bb0\u5f55\u9519\u8bef<\/li>\n<\/ul>\n<p>      debug:<br \/>\n        msg: &#8220;\u53d1\u751f\u9519\u8bef\uff1a{{ result }}&#8221;<br \/>\n      when: result.failed<\/p>\n<ul>\n<li>name: \u53d1\u9001\u901a\u77e5<\/li>\n<\/ul>\n<p>      shell: &#8220;notify_admin &#8216;{{ inventory_hostname }} &#8211; {{ result.msg }}'&#8221;<br \/>\n      when: result.failed and ansible_run_tags != [&#8216;skip_notify&#8217;]<\/p>\n<pre><code>\n---\n\n<h2>\u603b\u7ed3<\/h2>\n\n<h3>\u6838\u5fc3\u8981\u70b9\u56de\u987e<\/h3>\n\n\u2705 <strong>Ansible \u4f18\u52bf<\/strong>\uff1a\u65e0\u4ee3\u7406\u3001SSH \u7ba1\u7406\u3001YAML \u7b80\u5355  \n\u2705 <strong>\u6838\u5fc3\u6982\u5ff5<\/strong>\uff1aInventory\u3001Modules\u3001Playbooks\u3001Roles  \n\u2705 <strong>\u6279\u91cf\u7ba1\u7406<\/strong>\uff1a\u4e3b\u673a\u5206\u7ec4\u3001\u53d8\u91cf\u3001\u6a21\u677f  \n\u2705 <strong>\u5b89\u5168\u7ba1\u7406<\/strong>\uff1aSSH \u5bc6\u94a5\u3001Vault\u3001\u6743\u9650\u63a7\u5236  \n\u2705 <strong>\u6700\u4f73\u5b9e\u8df5<\/strong>\uff1aPlaybook \u7ec4\u7ec7\u3001CI\/CD\u3001\u9519\u8bef\u5904\u7406  \n\n<h3>\u6027\u80fd\u4f18\u5316\u5efa\u8bae<\/h3>\n\n<\/code><\/pre>\n<p>yaml<\/p>\n<h1>\u4f18\u5316\u914d\u7f6e<\/h1>\n<p>[defaults]<br \/>\nforks = 50  # \u5e76\u53d1\u6570<br \/>\ntimeout = 30<br \/>\nretry_files_enabled = False<\/p>\n<p>[ssh_connection]<br \/>\npipelining = True<br \/>\ncontrol_path = \/tmp\/ansible-ssh-%%h-%%p-%%r<\/p>\n<pre><code>\n<h3>\u63a8\u8350\u5de5\u4f5c\u6d41<\/h3>\n\n<\/code><\/pre>\n<p>Ansible \u5de5\u4f5c\u6d41\uff1a<\/p>\n<ol>\n<li>\u73af\u5883\u51c6\u5907<\/li>\n<\/ul>\n<p>   \u251c\u2500 \u5b89\u88c5 Ansible<br \/>\n   \u251c\u2500 \u914d\u7f6e SSH \u5bc6\u94a5<br \/>\n   \u2514\u2500 \u521b\u5efa Inventory<\/p>\n<ol>\n<li>\u5f00\u53d1 Playbook<\/li>\n<\/ul>\n<p>   \u251c\u2500 \u7f16\u5199\u4efb\u52a1<br \/>\n   \u251c\u2500 \u521b\u5efa Roles<br \/>\n   \u2514\u2500 \u6d4b\u8bd5\u9a8c\u8bc1<\/p>\n<ol>\n<li>\u90e8\u7f72\u6267\u884c<\/li>\n<\/ul>\n<p>   \u251c\u2500 \u5e72\u8fd0\u884c (&#8211;check)<br \/>\n   \u251c\u2500 \u5206\u6279\u90e8\u7f72<br \/>\n   \u2514\u2500 \u9a8c\u8bc1\u7ed3\u679c<\/p>\n<ol>\n<li>\u6301\u7eed\u7ef4\u62a4<\/li>\n<\/ul>\n<p>   \u251c\u2500 \u7248\u672c\u7ba1\u7406<br \/>\n   \u251c\u2500 \u6587\u6863\u66f4\u65b0<br \/>\n   \u2514\u2500 \u5b9a\u671f\u5ba1\u8ba1<br \/>\n&#8220;`<\/p>\n<p>&#8212;<\/p>\n<p>*\u672c\u6587\u6863\u6700\u540e\u66f4\u65b0\u65f6\u95f4\uff1a2026 \u5e74 04 \u6708 28 \u65e5*<br \/>\n*\u4f5c\u8005\uff1acreator | \u9002\u7528 Ansible 2.12+*<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ansible \u81ea\u52a8\u5316\u8fd0\u7ef4\uff1a100 \u53f0\u670d\u52a1\u5668\u7684\u6279\u91cf\u7ba1\u7406 \u5f15\u8a00 \u5728\u4e91\u8ba1\u7b97\u548c DevOps \u65f6\u4ee3\uff0c\u81ea\u52a8\u5316\u8fd0\u7ef4\u5df2\u6210\u4e3a&#8230;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-15942","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/www.srclibs.com\/index.php\/wp-json\/wp\/v2\/posts\/15942","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.srclibs.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.srclibs.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.srclibs.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.srclibs.com\/index.php\/wp-json\/wp\/v2\/comments?post=15942"}],"version-history":[{"count":0,"href":"https:\/\/www.srclibs.com\/index.php\/wp-json\/wp\/v2\/posts\/15942\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.srclibs.com\/index.php\/wp-json\/wp\/v2\/media?parent=15942"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.srclibs.com\/index.php\/wp-json\/wp\/v2\/categories?post=15942"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.srclibs.com\/index.php\/wp-json\/wp\/v2\/tags?post=15942"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}