應用部署和升級能夠用各類不一樣的策略來實現。最好的方法取決於應用程序自己、應用程序運行的基礎設施的能力、以及用戶應用程序的承諾的全部服務等級協議。無論你使用什麼策略,ansible都很是適合部署。本章中, 咱們將介紹一些經常使用的部署策略以及ansible特性在這些策略中展露頭腳的案例。咱們還討論兩種其餘部署,考慮兩種部署策略之間的共性,也就是:nginx
咱們講的第一種部署類型就是就地升級。這種類型的部署就是在現有的基礎設施上操做來更新原有應用程序。這種模型能夠看做是傳統的模型,建立新的基礎設施的時候存在時間和金錢上的高額開銷。git
在這種類型的升級過程當中,要減小宕機時間,通常的設計模式是經過在負載均衡後面的多個主機上部署應用。負載均衡扮演了一種在應用用戶和應用程序服務器之間的網關。對應用的請求會抵達負載均衡,依賴於具體配置,負載均衡會決定具體哪一個後端服務器來服務請求。shell
要對這種模式部署的應用執行就地升級滾動,每一個服務器(或服務器的一部分)會在負載均衡後面先禁用,而後升級、而後從新啓用來接受新請求。對池子中的剩餘機器重複作這樣的操做,直到全部的服務器都升級了。正由於只有部分可用應用服務器下線升級,應用總體上仍是保持對請求可用。固然,這裏須要有個假設前提,就是同時存在不一樣版本的應用的狀況下,應用執行OK。後端
讓咱們構建一個劇原本升級一個虛構的應用。咱們虛構的應用程序會運行在foo-app01到foo-app08這8臺服務器上,它們位於分組foo-app。這些服務器上面有一個簡單經過nginx服務的網站,應用內容來自git倉庫foo-app,經過變量foo-app.repo來定義。還有一個負載均衡服務器foo-lb,運行haproxy軟件,前置在這些應用服務器以前。設計模式
爲了操做foo-app服務器的子集,咱們須要利用serial模式。 這個模式會改變ansible如何執行劇情。默認狀況下,ansible會按順序遍歷任務中列舉的主機列表來執行劇本任務。劇本的每一個任務都要跨越全部主機執行完纔會執行下一個任務。若是咱們使用默認的模式,咱們第一個任務是移除負載均衡後面的每個應用服務,這樣就會致使咱們應用徹底的斷供(outage of our application)。而serial模式,可讓咱們對主機子集進行操做,這樣應用總體上來講仍是可用的,即使部分紅員下線了。在咱們的例子中,咱們使用serial數量2,爲了保持應用成員的大部分都是在線狀態:服務器
--- - name: Upgrade foo-app in place hosts: foo-app serial: 2
接下來咱們能夠建立咱們的任務了。第一個任務就是禁用負載均衡後面的主機。負載均衡運行在foo-lb主機上;然而,咱們是在foo-app主機上操做。所以,咱們須要使用delegate_to任務操做符代理任務。這個操做符指示ansible將鏈接到哪裏來執行任務,可是保持全部的原始主機上下文變量。咱們使用haproxy模塊來禁用來自foo-app後端池的當前主機。app
tasks: - name: disable member in balancer haproxy: backend: foo-app host: "{{ inventory_hostname }}" state: disabled delegate_to: foo-lb
主機禁用後,咱們就能夠升級foo-app內容了。咱們使用git模塊使用在foo-version變量中定義的指望版本號來更新內容路徑。咱們還會給這個任務添加一個notify處理器,若是內容更新結果改變的時候,來重啓nginx服務器。這個能夠每次都執行,這裏咱們使用這個做爲notify的例子:負載均衡
- name: pull stable foo-app git: repo: "{{ foo-app.repo }}" dest: /srv/foo-app/ version: "{{ foo-version }}" notify: - reload nginx
接下來,咱們須要在負載均衡裏邊從新啓用這個主機;然而,若是咱們接下來作這個任務的話,咱們會將舊版本就地退回,由於通知處理器尚未運行呢。所以,咱們須要提早觸發咱們的處理器,能夠經過meta: flush_handlers調用來實現,這點咱們前面已經瞭解過。less
- meta: flush_handlers
接下來,咱們能夠重啓啓用負載均衡後面的這個主機了。咱們能夠直接啓用它,並依賴負載均衡,在發送請求過去以前,一直等待直到機器健康。 然而,由於咱們運行的主機數量較少了,因此咱們須要確保剩下的主機都是健康的。咱們能夠利用wait_for任務等待,直到nginx服務再次服務鏈接。wait_for模塊會等待一個基於端口或文件路徑的條件。在咱們這個例子中,咱們等待端口80,以及那個端口應該在裏邊。若是它啓動了(默認狀況), 這就意味着它能夠接受請求了。ssh
- name: ensure healthy service wait_for: port: 80
最後,咱們能夠在haproxy中從新啓用這個成員。再一次,咱們委託任務給foo-lb:
- name: enable member in balancer haproxy: backend: foo-app host: "{{ inventory_hostname }}" state: enabled delegate_to: foo-lb
固然,咱們還須要定義咱們的reload nginx處理器:
handlers: - name: reload nginx service: name: nginx state: restarted
這個劇本運行的時候,就會對咱們的應用執行一個就地升級滾動。
就地升級策略的一個代替方案是擴容和縮容策略。這個策略已經變得後期流行了,得益於按需設施的自助特性,例如雲計算或虛擬化池子。具備從大的可用池中按需建立新的服務器的能力,意味着每個應用的部署均可以在全新的系統上發生。這種策略就避免了一個主機的問題。這些包含在長期運行系統上構建討厭的東西,例如:
每次從新全新的也能夠消除初始化部署和升級中的差別。可使用一樣的代碼路徑,下降升級應用時的意外風險。這種類型的安裝也能夠很是方便回滾,若是新版本執行沒達到預期的話。此外,隨着新系統取代舊系統,應用在升級過程當中不須要進入降級狀態。
接下來咱們再用擴容和縮容策略來實現咱們以前的升級劇本。咱們的模式是建立新的服務器、部署咱們的應用、驗證應用、將新服務器添加到負載均衡後面、而後從負載均衡裏邊移除舊服務器。 對於這個例子來講,咱們使用OpenStack Compute Cloud來啓動新實例:
--- - name: Create new foo servers hosts: localhost tasks: - name: launch instances os_server: name: foo-appv{{ version }}-{{ item }} image: foo-appv{{ version }} flavor: 4 key_name: ansible-prod security_groups: foo-app auto_floating_ip: false state: present auth: auth_url: https://me.openstack.blueboxgrid.com:5001/v2.0 username: jlk password: FAKEPASSW0RD project_name: mastery register: launch with_sequence: count=8
在這個任務中,咱們使用with_sequence在數量8個上循環。每一個循環上item會替換爲對應數字。這樣容許咱們能夠基於版本和數字來爲咱們應用建立8個全新實例。咱們也假設能夠有一個提早構建好的映像文件可使用,這樣咱們就無需作任何更多的實例配置了。爲了在未來的劇情中使用這些服務器,咱們須要將它們的細節添加到inventory中。 要實現這點,咱們註冊運行結果到啓動變量中,咱們將使用它們來建立運行時inventory實體:
- name: add hosts add_host: name: "{{ item.openstack.name }}" ansible_ssh_host: "{{ item.openstack.private_v4 }}" groups: new-foo-app with_items: launch.results
Deployment and upgrade strategies are a matter of taste. Each come with distinct advantages and disadvantages. Ansible does not possess an opinion on which is better, and therefore is well suited to perform deployments and upgrades regardless of the strategy. Ansible provides features and design patterns that facilitate a variety of styles with ease. Understanding the nature of each strategy and how Ansible can be tuned for that strategy will empower you to decide and design deployments for each of your applications.
In the next chapter, we'll cover topics that will help when things don't quite go as expected when executing Ansible playbooks.