Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
ansible³¬ÏêϸʹÓÃÖ¸ÄÏ
 
×÷Õߣº ÕÅС·²
  1805  次浏览      31
 2019-11-22
 
±à¼­ÍƼö:
±¾ÎÄÖ÷Òª½éÉÜÁËansibleÓÃÓÚ×Ô¶¯²¿ÊðºÍ»·¾³ÅäÖõÄʹÓÃÖ¸ÄÏ £¬ÒÔ¼°´´½¨×Ô¶¨ÒåÄ£¿éºÍDocker£¬Ï£Íû¶ÔÄúµÄѧϰÓÐËù°ïÖú¡£
±¾ÎÄÀ´×ÔÓÚ²©¿ÍÔ°£¬ÓÉ»ðÁú¹ûÈí¼þAlice±à¼­¡¢ÍƼö¡£

1 ΪʲôѡÔñAnsible

ÅäÖùÜÀí¡¢Ó¦Óò¿ÊðµÈ¡£ÅäÖùÜÀí¹¤¾ßÓÐChef, Puppet, SaltµÈ£¬Ó¦Óò¿Ê𣨽«´úÂë±àÒë»ò´ò°üÈ»ºó´«Êäµ½·þÎñÆ÷²¿Êð²¢Æô¶¯·þÎñ£©¹¤¾ßÓÐCapistrano£¬FabricµÈ£¬ansible¼¯Á½ÕßÓÚÒ»Éí£¬²Ù×÷ºÜ¼òµ¥µ«Êǹ¦ÄÜÇ¿´ó¡£´ËÍ⣬»¹¿ÉÒÔ¶Ô¶à¸ö·þÎñÆ÷½øÐзþÎñ±àÅÅ£¬Ö§³Öopenstack£¬amazon ec2£¬ dockerµÈ¡£

ansibleʹÓÃÁËÒ»¸öDSL£¨domain-specific language£©ÃèÊö·þÎñÆ÷״̬¡£Ö´ÐеÄÎļþ³ÆÎªplaybook£¬Îļþ¸ñʽΪyaml¡£ansible¼òÔ¼¶ø²»¼òµ¥¡£±ÈÆðpuppetµÄ·±ËöµÄÅäÖú͸´ÔÓÓï·¨( Puppet»ù´¡Æª4-°²×°¡¢ÅäÖò¢Ê¹ÓÃPuppet | PuppetÔËά×Ô¶¯»¯¾­Ñé·ÖÏí )£¬¼òÖ±ÊÇÒ»¹ÉÇåÁ÷¡£ ͼ2ÃèÊöÁËansibleÖ´Ðйý³Ì£¬Ö´ÐÐÁËÁ½¸ötaskºÍÒ»¸öhandler£¬ÏÈÊÇʹÓÃÁËÒ»¸öaptÄ£¿éÔÚweb1£¬web2£¬web3ÉÏÃæÖ´ÐÐÁ˰²×°nginxµÄÈÎÎñ£¬ÔÙÊÇÓÃtemplateÄ£¿é¿½±´ÁËÅäÖÃÎļþ¡£ÁíÍ⣬ִÐÐÁËÒ»¸önotify nginxµÄhandlerÖØÆôÁËnginx¡£

Ö´ÐÐÁ÷³Ì£º

1. ´´½¨Ò»¸öpython½Å±¾ÓÃÓÚ°²×°nginx°ü¡£

2. ¿½±´python½Å±¾µ½web1£¬web2£¬web3¡£

3. ·Ö±ðÔÚweb1£¬web2£¬web3ÉÏÖ´Ðиýű¾¡£

4. µÈ´ý½Å±¾ÔÚËùÓзþÎñÆ÷ÉÏÖ´ÐÐÍê±Ï¡£

5. ½Ó×ÅÖ´ÐÐÏÂÒ»¸ötask¡£

×¢ÒâµÄ¼¸µã£º

1.ÔÚ¸÷¸ö·þÎñÆ÷Ö´Ðнű¾µÄ¹ý³ÌÊDz¢Ðеģ¬Óиöforks²ÎÊý¿ÉÒÔÖ¸¶¨£¬Ä¬ÈÏÊÇ5£¬¼´Ò»´Î¿ÉÒÔÔÚ5¸ö·þÎñÆ÷Éϲ¢ÐÐÖ´Ðнű¾¡£

2.ÒªÔÚËùÓеķþÎñÆ÷¶¼Ö´ÐÐÍêµÚÒ»¸ötaskºó²Å»á½Ó×ÅÖ´Ðеڶþ¸ötask¡££¨Ð°汾ÐÂÔöÁËÒì²½²ÎÊý£¬Ò»¸ö·þÎñÆ÷ÔÚÖ´ÐÐÍêÁËËüµÄÈÎÎñºó¿ÉÒÔ²»µÈÆäËû·þÎñÆ÷Ö´ÐÐÍêÖ±½ÓÖ´ÐÐÏÂÒ»¸ötask£©¡£

3.ansibleÖ´ÐÐÈÎÎñ˳ÐòÓëplaybookÖеÄ˳ÐòÒ»Ö¡£

ÓÅÊÆ£º

Óï·¨Ò×¶Á¡£yaml->jsonºÃ±Èmarkdown->html¡£ansibleµÄplaybook¿ÉÒÔ±»³ÆÖ®Îª¿ÉÒÔÖ´ÐеÄREADME¡£

Ô¶³ÌÖ÷»ú²»ÐèÒª°²×°Èκζ«Î÷¡££¨ÕâÓеã¿ä´óÁË£¬python2.5+(python2.4+simplejsonÄ£¿é)ºÍsshÊDZØÐëµÄ£¬µ±È»ÕâÏÖÔÚÒѾ­ÊÇLinux·þÎñÆ÷±êÅäÁË£©

push-based¡£ÈçchefºÍpuppetÊÇpull-based£¬ÏȽ«ÎļþÐÞ¸ÄÍÆË͵½ÖÐÐÄ·þÎñÆ÷£¬ÆäËû·þÎñÆ÷µÄagent¶¨ÆÚÀ­È¡ÐµÄÅäÖùÜÀí½Å±¾²¢ÔÚ±¾»úÖ´ÐС£¶øÔÚansibleÊÇpush-basedµÄ£¬ÏÈÔÚÖÐÐÄ·þÎñÆ÷ÐÞ¸Äplaybook£¬Ö´ÐиÃplaybook£¬ansible»áÁ¬½Óµ½¸÷¸ö·þÎñÆ÷²¢Ö´ÐÐÄ£¿é¸Ä±ä·þÎñÆ÷״̬¡£push-basedµÄºÃ´¦¾ÍÊÇÖ»ÔÚÐèÒªµÄʱºò²Å²Ù¿ØÈ¥¸Ä±äÄ¿±ê·þÎñÆ÷״̬¡£Èç¹ûÄã¸üÇãÏòÓÚpull-basedģʽ£¬¿ÉÒÔÓÃansible-pull¡£

ansible¿ÉÒԺܷ½±ãµÄscaled down£¬µ¥»ú¸ú¶à»úûÓÐÊ²Ã´Çø±ð¡£ Simple things should be simple, complex things should be possible ¡£

ºÜÇáÁ¿¼¶µÄ³éÏó¡£²»ÏñpuppetÖ®ÀàµÄ¹¤¾ß£¬ÓкܸߵijéÏ󣬱ÈÈçÓÐpackageÕâ¸ö¸ÅÄÓÃÓÚ²»ÓÃÇø·Ö·þÎñÆ÷°æ±¾À´°²×°Ä£¿é¡£µ«ÊÇÔÚansibleÖУ¬ÌṩµÄÊÇaptºÍyumÄ£¿é£¬ÓÉÄã×Ô¼º²ÉÓ㬲»ÒªÔÙ¶îÍâѧһЩ³éÏóµÄÓï·¨£¬¼ò»¯ÄãµÄѧϰ³É±¾¡£Ò²ÓÐÈ˾õµÃÕâÊÇansibleµÄȱµã£¬ÓÅȱµãÓë·ñ£¬¸÷ÓÐÆÀÅС£

2 °²×°ÅäÖÃ

2.1 °²×°

pip install ansible

ÒÀÀµ»·¾³£ºpython

2.2 ÅäÖÃ

ÅäÖÃansible.cfgÎļþ£¬ansibleÅäÖÃÎļþѰÕÒ·¾¶£º

1. File specified by the ANSIBLE_CONFIG environment variable
2. ./ansible.cfg (ansible.cfg in the current directory)
3. ~/.ansible.cfg (.ansible.cfg in your home directory)
4. /etc/ansible/ansible.cfg

ansible.cfgÅäÖÃÎļþʵÀý

[defaults]
hostfile=/etc/ansible/hosts
private_key_file = /Users/ssj/.ssh/id_rsa_ansible
remote_user = ssj
remote_port = 22
host_key_checking = False

×¢Ò⣬Èç¹ûÊÇÔÚ·þÎñÆ÷ÉÏ£¬²»Òª·ÅÖÃprivate key£¬¿ÉÒÔͨ¹ýssh forward¡£

2.3 ²âÊÔ

¼òµ¥Ö´ÐÐÃüÁî²âÊÔÊÇ·ñ³É¹¦ ( -vvvv¿ÉÒÔ¿´µ½¸ü¶àϸ½ÚÐÅÏ¢)£¬¡±changed¡±:false±íʾִÐÐpingÄ£¿éûÓиıä·þÎñÆ÷״̬£¬¡±ping¡±:pong±íʾģ¿éÖ´ÐкóÊä³ö½á¹ûΪpong¡£ÄãÒ²¿ÉÒÔ½«pingÄ£¿é¸Ä³Écommand£¬¼ÓÉϲÎÊýÖ´ÐÐÖ¸¶¨ÃüÁî¡£±ÈÈç ansible testserver -m command -a uptime £¬µ±È»£¬commandÊÇĬÈÏÄ£¿é£¬Òò´Ë»¹¿ÉÒÔ¼ò»¯Îª ansible testserver -a uptime ¡£

hosts
[testserver]
127.0.0.1
run command£¬-i hosts¿ÉÒÔʡȥ¡£
ssj@ssj-mbp ~/ansible $ ansible testserver -i hosts -m ping
127.0.0.1 | SUCCESS => {
"changed": false,
"ping": "pong"
}

3 ʵÌå¹ØÏµÍ¼

playbook°üº¬ºÜ¶à¸öplay

playÖаüº¬name£¬tasks£¬hosts£¬vars£¬handlesÊôÐÔ¡£

tasksÖаüº¬¸÷¸öÕæÕýÖ´ÐеÄmodule£¬Èçapt£¬copy£¬file£¬ git£¬ svn£¬service£¬command£¬notify£¬mysqlµÈ¡£¾ßÌåµÄÄ£¿é²ÎÊýºÍʹÓÃÎĵµÔÚÕâÀï

4 Ò»¸öÀý×Ó

- name: Configure webserver with nginx and tls
hosts: webservers
sudo: True
vars:
key_file: /etc/nginx/ssl/nginx.key
cert_file: /etc/nginx/ssl/nginx.crt
conf_file: /etc/nginx/sites-available/default
server_name: localhost
tasks:
- name: Install nginx
apt: name=nginx update_cache=yes cache_valid_time=3600
- name: create directories for TLS certificates
file: path=/etc/nginx/ssl state=directory
- name: copy TLS key
copy: src=files/nginx.key dest={{ key_file }} owner=root mode=0600
notify: restart nginx
- name: copy TLS certificate
copy: src=files/nginx.crt dest={{ cert_file }}
notify: restart nginx
- name: copy nginx config file
template: src=templates/nginx.conf.j2 dest={{ conf_file }}
notify: restart nginx
- name: enable configuration
file: dest=/etc/nginx/sites-enabled/default src={{ conf_file }} state=link
notify: restart nginx
- name: copy index.html
template: src=templates/index.html.j2 dest=/usr/share/nginx/html/index.html mode=0644
handlers:
- name: restart nginx
service: name=nginx state=restarted

¿ÉÒÔ¿´µ½Óõ½ÁËapt£¬file£¬copy£¬template£¬notify£¬serviceµÈÄ£¿é¡£

×¢Ò⼸¸öÓï·¨µã£º

YAML truthy
true, True, TRUE, yes, Yes, YES, on, On, ON, y, Y

YAML falsey
false, False, FALSE, no, No, NO, off, Off, OFF, n, N

trueºÍyes£¬on»òÕß1¶¼ÊÇÒ»ÑùµÄÒâ˼£¬Ò»°ãÔÚÄ£¿é²ÎÊýÀïÃæÓÃyesºÍno£¬trueºÍfalseÔÚplaybookÖÐÆäËûµØ·½¡£

ÁíÍ⣬±ÈÈçÏÂÃæµÄÄ£¿é²ÎÊý·ÖÐÐд£¬¿ÉÒÔÔÚµÚÒ»ÐÐд > £¬ ºóÃæ¼¸Ðиú²ÎÊýÀ´ÊµÏÖ¡£

×¢ÒânotifyÊÇÑϸñ°´ÕÕËüÔÚplayÖж¨ÒåµÄ˳ÐòÖ´Ðе쬶ø²»ÊÇnotifyµ÷ÓõÄ˳ÐòÖ´Ðеġ£±ÈÈçÏÂÃæµÄplaybook£¬¾¡¹ÜÏÈnotifyµÄÊÇ handler test2 £¬Êµ¼ÊÖ´ÐÐʱʱ°´ÕÕplayÖÐhandlers¶¨ÒåµÄ˳Ðò£¬Ò²¾ÍÊÇÏÈÖ´ÐÐ handler test1¡£

!/usr/bin/env ansible-playbook
- name: test handlers
hosts: webservers
tasks:
- name: assure file exist
file: >
path=/tmp/test.conf
state=touch owner=ssj mode=0644
- name: task1
command: date
notify: handler test2


- name: task2
command: echo 'task2'
notify: handler test1


handlers:
- name: handler test1
command: echo 'handler test1'
- name: handler test2
command: echo 'handler test2'

5 ¸ü¶àϸ½Ú

5.1 inventory¸ñʽºÍÅäÖÃ

inventory¸ñʽ

[webserver]
127.0.0.1
dbserver1 ansible_ssh_host=127.0.0.1 ansible_ssh_port=22 color=red
dbserver2 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2200 color=green
>www.example.com
[dbserver] group
dbserver1
dbserver2<
[forum:children] groups of groups
webserver
dbserver

¿ÉÒÔÓ÷Ö×éµÄ·½Ê½£¬¿ÉÒÔÖ±½ÓÓÃÓòÃû(www.example.com)£¬Ò²¿ÉÒÔÓñðÃû(Èçtestserver2)+±äÁ¿Ö¸¶¨sshµÄipµØÖ·ºÍ¶Ë¿Ú£¬±ÈÈçansible_ssh_hostºÍcolor±äÁ¿¡£ÃüÁî ansible testserver2 -a date £¬Í¨³£ÎÒÃÇÒª¿ØÖƶą̀·þÎñÆ÷£¬ÓÚÊÇ¿ÉÒÔ·Ö×é·þÎñÆ÷£¬ÒªÔÚËùÓзþÎñÆ÷Ö´ÐпÉÒÔÓÃall¡£ ansible all -a date¡£

inventory³ýÁË¿ÉÒÔÖ¸¶¨Ö÷»úµÄ±äÁ¿ÈçÉÏÃæµÄcolorÖ®Í⣬»¹¿ÉÒÔ½«±äÁ¿·Ö×飬Ҳ¿ÉÒÔ¶ÔÖ÷»ú±äÁ¿µ¥¶À´æ´¢µ½Ò»¸öÎļþÖУ¬¸ñʽÈçÏ£¬×¢ÒâÈç¹ûhost_varsÖкÍgroup_varsÖÐÓÐÏàͬ±äÁ¿£¬ÔòÒÔhost_varsÖеÄΪ׼¡£host_vars±äÁ¿Ö»Äܱ¾Ö÷»úʹÓã¬group_varsÊDZ¾group¶¼¿ÉÒÔʹÓá£

group_vars/dbserver
-----------------------
db:
user: bbsdbuser
password: bbsdbpasswd
port: 3306
name: bbs
replica:
host: slavedb
port: 3307
host_vars/dbserver1
---------------------
db:
user:server1dbuser
password: server1password
master: true

ssj@ssj-mbp ~/ansible $ ansible dbserver1 -i hosts -a 'echo {{db.user}}' host_varsÓÅÏȼ¶¸ß
dbserver1 | SUCCESS | rc=0 >>
server1dbuser
----------------------------------------------------------
ssj@ssj-mbp ~/ansible $ ansible dbserver2 -i hosts -a 'echo {{db.master}}' dbserver2ËùÔÚµÄ×é±äÁ¿ÎļþûÓÐdb.master±äÁ¿£¬±¨´í¡£
dbserver2 | FAILED | rc=0 >>
the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'dict object' has no attribute 'master'

ÉõÖÁÖ§³Ö£º

[web]
web[1:20].example.com
web-[a-t].example.com

inventoryÎļþ»¹Ö§³Ö¶¯Ì¬µÄ£¬Í¨¹ý -i inventory ¿ÉÒÔÖ¸¶¨Ä¿Â¼»òÕßÎļþ£¬ÕâÑùĿ¼ÏÂÃæ¿ÉÒÔ·ÅÒ»¸öpython½Å±¾£¬ÓÃÀ´¶¯Ì¬»ñÈ¡Ö÷»úÁÐ±í¡£python½Å±¾Òª¿ÉÖ´ÐУ¬Í¬Ê±ÊµÏÖÏÂÃæÁ½¸öÃüÁ

--host=<hostname> for showing host details
--list for listing groups

×îºó£¬»¹¿ÉÒÔͨ¹ýadd_hostsÄ£¿éÔÚÔËÐÐʱÔö¼ÓhostÅäÖã¬Ê¹ÓÃgroup_byÄ£¿éÔÚÔËÐÐʱ´´½¨group¡£±ÈÈçͨ¹ý ansible_distributionÀ´¸ù¾Ý²Ù×÷ϵͳ´´½¨²»Í¬µÄ×飬ÔÙ·Ö±ð°²×°Èí¼þ¡£

- name: group hosts by distribution
hosts: myhosts
gather_facts: True
tasks:
- name: create groups based on distro
group_by: key={{ ansible_distribution }}
- name: do something to Ubuntu hosts
hosts: Ubuntu
tasks:
- name: install htop
apt: name=htop
...
- name: do something else to CentOS hosts
hosts: CentOS
tasks:
- name: install htop
yum: name=htop
...

inventoryĬÈÏÅäÖÃ

¼¸¸ö²ÎÊý½âÊÍÏ£º

- ansible_connection: sshÁ¬½Ó·½Ê½£¬Ä¬ÈÏÊÇsmart£¬Ò²¾ÍÊÇ¿´±¾µØ»úÆ÷ÊÇ·ñ°²×°ÁËssh¿Í»§¶ËÇÒÖ§³ÖControlPersistÌØÐÔ¡£Èç¹ûÖ§³Ö£¬ÔòʹÓñ¾µØµÄssh¿Í»§¶Ë£¬Èç¹û²»Ö§³Ö£¬ÔòʹÓÃÒ»¸ö»ùÓÚpythonµÄssh¿Í»§¶Ë¿âparamiko¡£

- ansible_shell_type: ansibleÈÏΪµÄÔ¶³Ì·þÎñÆ÷Ö´ÐÐscriptµÄshell£¬Ä¬ÈÏÈÏΪÊÇ/bin/sh£¬µ±È»Ò²¿ÉÒÔÉèÖÃΪcsh£¬fishµÈ£¬Èç¹û·þÎñÆ÷Ö§³ÖµÄ»°¡£

- ansible_python_interpreter: ·þÎñÆ÷python½âÊÍÆ÷µÄ·¾¶¡£Èç¹ûÄãµÄ·þÎñÆ÷python½âÊÍÆ÷²»ÔÚÕâ¸öĿ¼£¬ÕâÒªÐ޸ĸÃÅäÖá£

- ansible_*_interpreter: Èç¹ûÓõÄÊÇÒ»¸ö×Ô¶¨ÒåµÄÄ£¿é£¬²»ÊÇpythonµÄ£¬±ÈÈçruby£¬ÔòÉèÖøÃÖµÖ¸¶¨½âÊÍÆ÷·¾¶£¨±ÈÈç/usr/bin/ruby£©¡£

5.2 ±äÁ¿ºÍFacts

±äÁ¿

±äÁ¿¿ÉÒÔÔÚplayÖÐͨ¹ývarsÀ´Ö¸¶¨£¬Ò²¿ÉÒÔͨ¹ývar_fileÖ¸¶¨Ò»¸öÎļþ£¬ÎļþÖд洢±äÁ¿¡£Èç֮ǰµÄnginxµÄplaybook¿ÉÒԸijÉÕâÑù£º

vars_files:
- nginx.yml
nginx.ymlÎļþÄÚÈÝ
key_file: /etc/nginx/ssl/nginx.key
cert_file: /etc/nginx/ssl/nginx.crt
conf_file: /etc/nginx/sites-available/default
server_name: localhost

¿ÉÒÔÔÚplayÖÐʹÓÃdebugÄ£¿é´òÓ¡±äÁ¿µÄÖµ£¬×¢ÒâdebugÖ§³ÖµÄ²ÎÊýÓÐvar£¬msgµÈ£¬varÖеıäÁ¿²»ÒªÊ¹Óà {{}}°ü¹ü¡£

!/usr/bin/env ansible-playbook
- name: test name
hosts: webserver
vars:
myvar: testmyvar
tasks:
- debug: var=myvar
- name: capture output of id command
command: id -un
register: login
- debug: var=login

ʹÓÃregisterÀ´×¢²áÒ»¸ö±äÁ¿ºóÃæÊ¹Óã¬register×¢²áµÄ±äÁ¿ÔÚÕâ¸öplaybookµÄÆäËûplayÖÐÒ²ÊÇ¿ÉÒÔʹÓõ쬲»¾ÖÏÞÓÚÕâÒ»¸öplay¡£±ÈÈçcommandÄ£¿éµÄÊä³öÈçÏÂËùʾ£¬¿ÉÒÔͨ¹ýlogin.stdoutµÃµ½Óû§Ãû¡£×¢Òⲻͬģ¿éµÄÊä³ö¿ÉÄÜÊDz»Ò»ÑùµÄ£¬Í¬Ò»¸öÄ£¿éÔÚ²»Í¬Çé¿öÏÂÒ²²»Ò»Ñù£¬±ÈÈçaptÄ£¿é°²×°nginx£¬Èç¹û»úÆ÷ÒѾ­°²×°ÁËnginx£¬ÔòÊä³öÀïÃæchangeΪfalse£¬¶øÇÒ²»»áÓÐstdout£¬stderrºÍstdout_linesÕâЩkey¡£Èç¹ûÄ£¿éÖ´Ðгö´í£¬ÔòÆäËûµÄhostĬÈϲ»»áÔÙÖ´ÐУ¬¿ÉÒÔÉèÖà ignore_erros:True ºöÂÔÄ£¿éµÄ´íÎó¡£

ÆäËûÖ¸¶¨±äÁ¿µÄ·½Ê½Èç host_varsĿ¼£¬group_varsĿ¼µÈ¡£

{
"changed": true,
"cmd": [
"id",
"-un"
],
"delta": "0:00:00.007369",
"end": "2016-11-17 15:09:49.061725",
"rc": 0,
"start": "2016-11-17 15:09:49.054356",
"stderr": "",
"stdout": "ssj",
"stdout_lines": [
"ssj"
],
"warnings": []
}

Èç¹ûÔÚplaybookÖÐÅäÖÃÁË gather_facts:True£¬Ôò»á¿´µ½ÕæÕýµÄÈÎÎñ¿ªÊ¼Ç°£¬»áÏÈÖ´ÐÐÒ»¸ö[setup]µÄÄ£¿é£¬ÓÃÓÚÊÕ¼¯·þÎñÆ÷ÐÅÏ¢£¬°üÀ¨cpu¼Ü¹¹£¬²Ù×÷ϵͳÀàÐÍ£¬ipµØÖ·µÈÐÅÏ¢¡£ÕâЩÐÅÏ¢´æ´¢ÔÚÌØ¶¨µÄ±äÁ¿ÖУ¬ÎÒÃdzÆÖ®Îªfacts¡£Èç¹ûÄãµÄplaybookÖв»ÐèÒªÕâЩÐÅÏ¢£¬Ò²¿ÉÒÔÉèÖÃgather_facts:FalseÀ´¼Ó¿ìplaybookÖ´ÐÐËÙ¶È£¬ÊÕ¼¯·þÎñÆ÷ÐÅÏ¢ÐèÒª»¨·Ñ²»ÉÙʱ¼äµÄ¡£

ͨ¹ýÃüÁî ansible webserver -m setup ¿ÉÒÔ¿´µ½ansibleµÄgathter_factsµÄÊä³öÄÚÈÝ£¬ÈíÓ²¼þÐÅÏ¢¶¼ÓС£ÒòΪÐÅϢ̫¶à£¬»¹¿ÉÒÔͨ¹ýÔÚsetupÄ£¿é¼ÓÉϲÎÊýfilterÀ´É¸Ñ¡ÄãÐèÒªµÄÄÚÈÝ£¬Èç¹ûÖ»ÐèÒªÍøÂçÐÅÏ¢£¬¿ÉÒÔÕâÑù£º ansible webserver -m setup -a 'filter=ansible_eth*¡¯ £¬ÆäÖÐansible_factsÕâ¸ökeyÊǹ̶¨µÄ¡£

127.0.0.1 | SUCCESS => {
"ansible_facts": {
"ansible_eth0": {
"active": true,
"device": "eth0",
"ipv4": {
"address": "xxx.xxx.xxx.xxx",
"broadcast": "xxx.xxx.xxx.xxx",
"netmask": "xxx.xxx.xxx.xxx.xxx",
"network": "xxx.xxx.xxx.xxx"
},
"macaddress": "xx.xx.xx.xx.xx.xx",
"module": "bnx2",
"mtu": 1500,
"pciid": "0000:10:00.0",
"promisc": false,
"type": "ether"
},
},
"changed": false
}

¿ÉÒÔÔÚ¶¨Òå±¾µØfacts£¬ÔÚ /etc/ansible/facts.d/ Ŀ¼Ð½¨example.factÎļþ£¬ÄÚÈÝÈçÏ£º

[book]
title=Ansible: Up and Running
author=Lorin Hochstein
publisher=O'Reilly Media

È»ºóÔÚÔËÐÐplaybookµÄʱºò¾Í¿ÉÒÔͨ¹ý ansible_local¶ÁÈ¡ÕâЩ±äÁ¿ÁË¡£

ÁíÍ⣬»¹¿ÉÒÔͨ¹ý set_fact Ä£¿éÉèÖñäÁ¿£¬±ÈÈç֮ǰµÃµ½ÁËÒ»¸öÃüÁîµÄÊä³ö£¬registerµ½Ò»¸ö±äÁ¿£¬È»ºó°ÑÎÒÃÇÐèÒªµÄ±äÁ¿ÌáÈ¡³öÀ´ÓÃset_fact´æ´¢µ½ÁíÍâÒ»¸ö±äÁ¿ÖУ¬¼ò»¯Á˱äÁ¿µÄÒýÓá£

- name: test name
hosts: webserver
gather_facts: True
tasks:
- name: print ansible_local
debug: var=ansible_local
- name: capture output of id command
command: id -un
register: login
ignore_errors: True
- set_fact: loginuser={{ login.stdout }}
- name: show login user
debug: var=loginuser

ÄÚÖñäÁ¿

ÃüÁîÐд«µÝ±äÁ¿

»¹¿ÉÒÔÔÚÔËÐÐplaybookµÄʱºòÔÚÃüÁîÐд«µÝ±äÁ¿¡£Èç¹ûÒª´«µÝÒ»¸ö°üº¬±äÁ¿µÄÎļþ£¬¿ÉÒÔÓà $ ansible-playbook greet.yml -e @greetvars.yml ¡£

- name: pass a message on the command line
hosts: localhost
vars:
greeting: "you didn't specify a message"
tasks:
- name: output a message
debug: msg="{{ greeting }}"
$ ansible-playbook greet.yml -e greeting=hiya

±äÁ¿ÓÅÏȼ¶

ansibleÔÚºÜ¶àµØ·½¿ÉÒÔÉèÖñäÁ¿£¬¾¡Á¿²»ÒªÖØÃû¡£ÓÅÏȼ¶Óɸߵ½µÍÈçÏ£º

- ÃüÁîÐеIJÎÊý£¬ ÉÏÃæµÄ -e greeting=¡®hello¡¯ ¡£

- host, groupÖеıäÁ¿£¬²»¹ÜÊÇÔÚinventoryÖл¹ÊÇyamlÎļþÖж¨ÒåµÄ¡£

- Facts±äÁ¿

- roleĿ¼Ï嵀 defaults/main.yml ¡£

5.3 playbook񻵋

ʵÓÃÄ£¿é

Èç¹ûÏëÔÚ¿ØÖÆ»úÆ÷¶ø²»ÊÇÔ¶³Ì»úÆ÷ÔËÐÐÃüÁ¿ÉÒÔÓÃlocal_action¡£

Èç¹û»úÆ÷ûÓÐÆô¶¯ÆðÀ´£¬ÐèÒªÏȵȴý»úÆ÷Æô¶¯ÔÙÖ´ÐÐplay£¬ÓÃwait_forÄ£¿é¡£

- name: Deploy mezzanine
hosts: web
gather_facts: False
vars & vars_files section not shown here
tasks:
- name: wait for ssh server to be running
local_action: wait_for port=22 host="{{ inventory_hostname }}" search_regex=OpenSSH
- name: gather facts
setup:

Èç¹û²»ÏëÒ»´ÎÔÚËùÓеÄhosts¶¼Ö´ÐУ¬¿ÉÒÔÉèÖÃserial²ÎÊýÀ´ÉèÖÃÿ´ÎÖ´Ðм¸¸öhost£¬±ÈÈçÉý¼¶·þÎñÆ÷£¬ÎÒÃDz»ÏëÓ°Ïì·þÎñ£¬»áÒ»¸öÒ»¸öÅÜ¡£¿ÉÒÔÉèÖÃmax_fail_percentageÀ´Ö¸¶¨×î´óʧ°ÜµÄ±ÈÂÊ£¬±ÈÈçÉèÖÃΪ25%£¬ÔòÈç¹ûÓÐ4̨»úÆ÷£¬ÓÐ2̨ÈÎÎñÖ´ÐÐʧ°ÜÔòÖÕÖ¹Õû¸öplay£¬ÆäËûÈÎÎñ²»ÔÙÖ´ÐС£

name: upgrade packages on servers behind load balancer
hosts: myhosts
serial: 1
max_fail_percentage: 25
tasks:
tasks go here

һЩÊý¾ÝÈçdbÃÜÂëµÈ²»ÄÜÖ±½ÓÌá½»µ½´úÂë¿â£¬¿ÉÒÔÌá½»Ò»¸ö¼ÓÃܵİ汾¡£¼ÓÃÜÎļþ¿ÉÒÔÓÃansible-vault¹¤¾ß¡£ÔËÐÐplaybookµÄʱºò¼ÓÉϲÎÊý

ansible-vault encrypt secrets.yml
ansible-vault create secrets.yml
ansible-vault view secrets.yml
$ ansible-playbook test.yml --ask-vault-pass
$ ansible-playbook mezzanine --vault-password-file ~/password.txt

¿ÉÒÔÓÃðºÅ:±íʾºÏ²¢·þÎñÆ÷×飬:& Çó½»¼¯µÈ¡£

Ö¸¶¨ÔËÐеÄhosts¿ÉÒÔÔÚÃüÁîÐмÓÉÏ ¡ªlimit ¡£

ansible-playbook -l 'staging:&database' playbook.yml

ansible-playbook ¡ªlimit 'staging:&database' playbook.yml

Filters

filter¿ÉÒÔÓÃÔÚºÜ¶à·½Ãæ£¬±ÈÈçĬÈÏÖµfilter¡£Èç¹ûdatabase_hostûÓж¨Ò壬ÔòHOSTµÄÖµÉèÖÃΪlocalhost¡£

"HOST": "{{ database_host | default('localhost') }}"

Õë¶ÔÈÎÎñ·µ»ØÖµµÄfilter¡£¿ÉÒÔµÄȡֵÓÐ failed£¬changed£¬skipped£¬successµÈ¡£

failed_when: result|failed

Îļþ·¾¶µÄfilter¡£

vars:
homepage: /usr/share/nginx/html/index.html
tasks:
- name: copy home page
copy: src=files/{{ homepage | basename }} dest={{ homepage }}

×Ô¶¨Òåfilter¡£

дһ¸ö×Ô¶¨ÒåµÄfilter£¬·ÅÔÚÏîÄ¿µÄ filter_plugins Ŀ¼Ï¼´¿É¡£ÏÂÃæÊÇÒ»¸öÓÃÓÚ×Ö·û´®·Ö¸îµÄfilterÄ£¿é£¬Ê¹ÓÃʱʹÓÃfilterÓï·¨¼´¿É¡£

from ansible import errors
def split_string(string, seperator=' '):
try:
return string.split(seperator)
except Exception, e:
raise errors.AnsibleFilterError('split plugin error: %s, string=%s' % str(e),str(string) )
class FilterModule(object):
def filters(self):
return {
'split' : split_string,
}

²éÕÒ±äÁ¿¿ÉÒÔͨ¹ýlookupʵÏÖ£¬Ö§³Öfile£¬redis£¬pipe£¬cvsfileµÈ¶àÖÖ¸ñʽ¡££¨redisµÄÐèÒª°²×°pythonµÄredisÄ£¿é£©

¸´ÔÓÑ­»·

with_items

with_lines

with_fileglob

with_dict

...

debugÄãµÄplaybook

¼ì²éÓï·¨£ºansible-playbook --syntax-check playbook.yml
²é¿´hostÁÐ±í£ºansible-playbook --list-hosts playbook.yml
²é¿´taskÁÐ±í£ºansible-playbook --list-tasks playbook.yml
¼ì²éģʽ(²»»áÔËÐÐ): ansible-playbook --check playbook.yml
diffģʽ(²é¿´Îļþ±ä»¯)£º ansible-playbook --check --diff playbook.yml
´ÓÖ¸¶¨µÄtask¿ªÊ¼ÔËÐУºansible-playbook --start-at-task="install packages" playbook.yml
Öð¸ötaskÔËÐУ¬ÔËÐÐǰÐèÒªÄãÈ·ÈÏ£ºansible-playbook --step playbook.yml
Ö¸¶¨tags£ºansible-playbook --tags=foo,bar playbook.yml
Ìø¹ýtags£ºansible-playbook --skip-tags=baz,quux playbook.yml

6 ½ÇÉ«(Roles)

6.1 ½ÇÉ«»ù±¾½á¹¹

roles¿ÉÒÔ¼ò»¯playbook±àд£¬ÈÃplaybook¸üÇåÎúºÍ·½±ã¸´Óá£Ò»¸öÃûΪdatabaseµÄroleµÄĿ¼½á¹¹ÈçÏ£¬ÕâЩĿ¼¶¼ÊÇ¿ÉÑ¡µÄ£¬Èç¹ûÄãµÄ½ÇɫûÓÐÈκÎhandler£¬Ôò²»ÐèÒªhandlersĿ¼¡£rolesµÄ²éÕÒ·¾¶Ä¬ÈÏÊÇ/etc/ansible/roles£¬Ò²¿ÉÒÔÔÚ /etc/ansible/ansible.cfgµÄroles_pathÖÐÉèÖá£

roles/database/tasks/main.yml
Tasks
roles/database/files/
Holds files to be uploaded to hosts
roles/database/templates/
Holds Jinja2 template files
roles/database/handlers/main.yml
Handlers
roles/database/vars/main.yml
Variables that shouldn¡¯t be overridden
roles/database/defaults/main.yml
Default variables that can be overridden
roles/database/meta/main.yml
Dependency information about a role

ÔÚ½ÇɫִÐÐÈÎÎñǰ×öһЩǰÖù¤×÷£¬ÈÎÎñÖ´ÐÐÍêºó×öһЩºóÖô¦Àí¡£

- name: test
hosts: dbserver
vars_files:
- secrets.yml
pre_tasks:
- name: update the apt cache
apt: update_cache=yes
roles:
- role: database
post_tasks:
- name: send email
command: xxx

6.3 ÒÀÀµ½ÇÉ«

Èç¹ûÅÂÒÅ©һЩÈÎÎñ£¬±ÈÈçÉèÖÃntpÖ®ÀàµÄ£¬¿ÉÒÔʹÓÃÒÀÀµ½ÇÉ«µÄ¹¦ÄÜ¡£ÕâÑùÔÚÖ´ÐÐÄãµÄ½ÇÉ«ÈÎÎñʱ»áÏÈÖ´ÐÐÒÀÀµ½ÇÉ«¡£

roles/database/meta/main.yml
dependencies:
- { role: ntp, ntp_server=ntp.ubuntu.com }

6.4 Ansible Galaxy

¿ÉÒÔͨ¹ýansible galaxy¹¤¾ß·½±ãµÄ´´½¨Ò»¸ö½ÇɫĿ¼¡£

ansible-galaxy init -p playbooks/roles database

Èç¹û²»ÓÃ-pÖ¸¶¨Â·¾¶£¬ÄÇôĬÈÏÊÇ»áÔÚµ±Ç°Ä¿Â¼´´½¨½ÇÉ«µÄĿ¼½á¹¹¡£´´½¨ºóµÄĿ¼½á¹¹ÈçÏ£º

playbook/roles/database
©À©¤©¤ README.md
©À©¤©¤ defaults
©¦ ©¸©¤©¤ main.yml
©À©¤©¤ files
©À©¤©¤ handlers
©¦ ©¸©¤©¤ main.yml
©À©¤©¤ meta
©¦ ©¸©¤©¤ main.yml
©À©¤©¤ tasks
©¦ ©¸©¤©¤ main.yml
©À©¤©¤ templates
©À©¤©¤ tests
©¦ ©À©¤©¤ inventory
©¦ ©¸©¤©¤ test.yml
©¸©¤©¤ vars
©¸©¤©¤ main.yml

ansible galaxy»¹ÊÇÒ»¸ö¿ªÔ´µÄ½ÇÉ«¿â£¬Äã¿ÉÒÔÔÚÆäÖÐÏÂÔØµ½Ðí¶àÆäËûÈËдºÃµÄ½ÇÉ«´úÂë»òÕßÌá½»×Ô¼ºµÄ½ÇÉ«´úÂë¡£½ÇÉ«²Ö¿âµÄʹÓÃ˵Ã÷ÔÚÕâÀï¡£

6.5 Ansible Tower

ansible towerÊÇansible¹«Ë¾ÌṩµÄÒ»Ì×ÉÌÓõÄweb¹ÜÀíÆ½Ì¨£¬Ò²ÓÐÊÔÓð汾£¬»¹Ã»ÓÐÊÔÓùý£¬ºóÐøÊ¹ÓÃÁËÔÙ²¹³ä¡£

7 ¼ÓËÙÄãµÄansible

7.1 SSH ControlPersist

ControlMaster auto
ControlPath $HOME/.ansible/cp/ansible-ssh-%h-%p-%r
ControlPersist 60s

7.2 Pipelining£¨ansibleµÄÌØÐÔ)

ansibleͨ³£Ö´ÐеÄÔ­ÀíÊÇÔÚ ~/.ansibleÏÂÃæ´´½¨Ò»¸öÁÙʱĿ¼(ͨ¹ýssh)£¬È»ºóͨ¹ýsftp»òÕßscp¿½±´python½Å±¾µ½ÁÙʱĿ¼£¬È»ºóÖ´ÐÐÕâ¸ö½Å±¾´úÂ루ÔÙ´Îͨ¹ýssh£©¡£Ê¹ÓÃpipeline¿ÉÒÔʹµÃÕâЩ²Ù×÷Ö»ÒªÒ»¸össhÁ¬½ÓÈ¥Ö´ÐÐpython½Å±¾¡£¼´±ãÊÇ¿ªÆôÁËControlPersist£¬Õâ¸öÐÔÄÜÌáÉýÒ²ºÜ¿É¹Û¡£ÔÚÅäÖÃÎļþÖмÓÈëpipelining=true¼´¿É¿ªÆô¡£

ÐèҪעÒâµÄÊÇ£¬¿ªÆôpipelingÒª¹Ø±Õ·þÎñÆ÷µÄrequiretty¹¦ÄÜ¡£Ôö¼ÓÎļþ/etc/sudoers.d/disable-requiretty£¬ÆäÖеÄÄÚÈÝΪ Defaults:ansibleuser !requiretty£¬ansibleuserΪÄãµÄÓû§Ãû¡£

7.3 Fact Cache

Èç¹ûÄã²»ÐèÒªÓõ½·þÎñÆ÷ÐÅÏ¢£¬¿ÉÒԹرջñÈ¡factµÄ¹¦ÄÜ£¬ÕâÑùÒ²¿ÉÒÔ¼Ó¿ìplaybookµÄÖ´ÐÐЧÂÊ¡£ÅäÖÃÎļþÖмÓÈë gathering = explicit¼´¿É£¬ÕâÑùÄãÒª»ñÈ¡·þÎñÆ÷ÐÅÏ¢£¬ÐèÒªÏÔʾµÄÔÚplayÖÐÖ¸¶¨¡£

Èç¹ûÒªÓõ½factÐÅÏ¢£¬¿ÉÒÔʹÓÃfact»º´æ£¬ÕâÑùÿ¸ö»úÆ÷µÄfactÐÅÏ¢Ö»»á»ñȡһ´Î¶ø²»ÊÇÿ´Î¶¼È¥»ñÈ¡¡£fact»º´æÖ§³Öjson£¬redis£¬memcached¡£Èç¹ûÓÃredisÔòÐèÒªÔÚ¿ØÖÆ»úÉϰ²×°pythonµÄredisÄ£¿é£¬×ÔÈ»redisÒ²ÊÇÒª°²×°µÄ¡£

[defaults]
gathering = smart
24-hour timeout, adjust if needed
fact_caching_timeout = 86400
You must specify a fact caching implementation
JSON file implementation
fact_caching = jsonfile //»òÕßredis£¬memcached
fact_caching_connection = /tmp/ansible_fact_cache

7.4 Parallelism

¿ÉÒÔÉèÖÃANSIBLE_FORKS»·¾³±äÁ¿»òÕßÔÚÅäÖÃÎļþ¼ÓÉÏforks=nÀ´Ö¸¶¨²¢ÐÐÖ´ÐеÄhostµÄÊýÄ¿¡£

7.5 ¹ØÓÚÒì²½

ansibleµÄ1.7°æ±¾¿ªÊ¼Ôö¼ÓÁËÒì²½²ÎÊý async£¬Ò²¾ÍÊÇ˵ִÐÐÒ»¸öʱ¼äºÜ³¤µÄÈÎÎñʱ£¬¿ÉÒÔ²»ÓõȴýËü½áÊø£¬¶øÊÇÖ±½ÓÏÈÖ´ÐкóÃæµÄÈÎÎñ£¬ÔÚºóÐøµÄplayÖж¨Ê±¼ì²éÈÎÎñÖ´Ðнá¹û¼´¿É¡£

Óм¸µã×¢Òâһϣ¬Ò»¸öÊÇasync²ÎÊý£¬ÊÇÖ¸ÈÎÎñÖ´Ðеij¬Ê±Ê±¼ä£¬Èç¹ûÕâ¸öʱ¼äÉèÖõıÈÈÎÎñÖ´ÐÐʱ¼ä¶Ì£¬ÔòÈÎÎñ»á³¬Ê±Ê§°Ü¡£pollֵΪÂÖѯÈÎÎñ״̬µÄʱ¼ä¼ä¸ô£¬Èç¹ûÉèÖÃΪ0£¬±íʾÆô¶¯²¢ºöÂÔ£¬Ò²¾ÍÊÇ˵ÉèÖÃΪ0²ÅÊÇÕæÕýµÄ¿ªÊ¼Òì²½Ö´ÐУ¬Ò²¾ÍÊÇÖ±½ÓÖ´ÐкóÃæµÄtask£¬¶øÎªÁËÖªµÀÒì²½ÈÎÎñÖ´ÐеĽá¹û£¬¿ÉÒÔÓÃasync_statusÀ´ÊµÏÖ¡£Èç¹ûpollÉèÖÃΪ·Ç0Öµ£¬Ôò»¹ÊÇ×èÈûÖ´Ðе쬲¢·ÇÒì²½¡£

- hosts: dbserver
tasks:
- name: simulate long running op (15 sec), wait for up to 45 sec, poll every 5 sec
command: /bin/sleep 15
async: 20
poll: 0
register: asynctest
- name: check async status
async_status: jid="{{ asynctest.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 30
delay: 2

8 ´´½¨×Ô¶¨ÒåÄ£¿é

ÔÚijЩÇé¿öÏ£¬¿ÉÄÜansible×Ô´øµÄÄ£¿é²»ÄÜÂú×ãÄãµÄÐèÇó£¬ÐèÒª×Ô¶¨ÒåÄ£¿é¡£¿ÉÒÔͨ¹ýpython»òÕßbashÀ´Ð´×Ô¶¨ÒåÄ£¿é£¬·ûºÏansibleµÄÄ£¿é±àд±ê×¼¼´¿É£¬ÕâÀïÓкÜÏêϸµÄÎĵµ¡£

9 Docker

dockerÊÇĿǰºÜ»ð±¬µÄ¼¼Êõ£¬ËüÌṩÁËÒ»Ì×Ô¶³ÌAPI¹©µÚÈý·½³ÌÐòµ÷Óã¬ansibleµÄdockerÄ£¿é¾ÍÊÇʹÓÃÁËÕâÌ×API¶Ôdocker²Ù×÷¡£ansibleÓÃÔÚdockerÉÏÖ÷ÒªÓÐÁ½µã£ºÒ»ÊDZàÅÅdockerÈÝÆ÷¡£Í¨³£Ò»¸öϵͳÐèÒªºÜ¶à¸ödockerÈÝÆ÷À´Ö§³Ö£¬Ã¿¸öÈÝÆ÷¶¼ÔËÐÐÒ»¸ö·þÎñ¡£·þÎñÖ®¼äÐèÒªÏ໥ͨÐÅ£¬Í¬Ê±ÄãÒ²Òª±£Ö¤ÈÝÆ÷Æô¶¯µÄ˳ÐòµÈ£¬Ô­Éúdocker²¢Ã»ÓÐÕâЩ¹¤¾ßÖ§³Ö£¬ansibleÔòÊǷdz£ºÏÊʵÄÒ»¸öÑ¡Ôñ¡£¶þÊÇ´´½¨¾µÏñ¡£¹Ù·½µÄ·½Ê½ÊÇͨ¹ýDockerfileÀ´´´½¨¾µÏñ£¬µ«ÊÇͨ¹ýansibleÀ´ÊµÏÖ¸ü¼Ó¼òµ¥·½±ã¡£

»ùÓÚdockerµÄÓ¦ÓõÄÉúÃüÖÜÆÚÊÇÕâÑùµÄ£º

1. ÔÚ±¾µØ»úÆ÷´´½¨docker¾µÏñ¡£

2. ½«docker¾µÏñpushµ½registry¡£

3. Ô¶³Ì»úÆ÷ÉϽ«¾µÏñ´ÓregistryÉÏpullÏÂÀ´¡£

4. ÔÚÔ¶³Ì»úÆ÷ÉÏÆô¶¯ÈÝÆ÷¡£

ʹÓÃansibleÖ®ºó£¬ÔòÊÇÏÂÃæÕâÑùµÄ£º

1. дºÃÓÃÀ´´´½¨docker¾µÏñµÄplaybook¡£

2. ÔËÐÐplaybookÀ´´´½¨¾µÏñ¡£

3. ½«docker¾µÏñÍÆË͵½registry¡£

4. дºÃÒ»¸öÀ­È¡docker¾µÏñ²¢Æô¶¯ÈÝÆ÷µÄplaybook¡£

5. Ö´ÐÐplaybookÀ­È¡ºÍÆô¶¯ÈÝÆ÷¡£

 
   
1805 ´Îä¯ÀÀ       31
Ïà¹ØÎÄÕÂ

DevOpsתÐÍÈÚÈëµ½ÆóÒµÎÄ»¯
DevOps ÄÜÁ¦Ä£ÐÍ¡¢Ñݽø¼°°¸ÀýÆÊÎö
»ùÓÚ DevOps ÀíÄîµÄ˽ÓÐ PaaS ƽ̨ʵ¼ù
΢Èí¿ª·¢ÍŶӵÄDevOpsʵ¼ùÆôʾ
Ïà¹ØÎĵµ

DevOpsÇý¶¯Ó¦ÓÃÔËά±ä¸ïÓë´´ÐÂ
ÔËά¹ÜÀí¹æ»®
ÈçºÎʵÏÖÆóÒµÓ¦Óò¿Êð×Ô¶¯»¯
ÔËά×Ô¶¯»¯Êµ¼ù֮·
Ïà¹Ø¿Î³Ì

×Ô¶¯»¯ÔËά¹¤¾ß£¨»ùÓÚDevOps£©
»¥ÁªÍøÔËάÓëDevOps
MySQLÐÔÄÜÓÅ»¯¼°ÔËάÅàѵ
ITϵͳÔËά¹ÜÀí