# 第1章 入門
建立Docker生產環境系統的首要任務,是以一個有助于想象各組件如何相互配合的方式來理解其術語。與其他快速發展的技術生態系統一樣,我們可以預見,Docker野心勃勃的市場營銷、不完善的文檔以及過時的博客文章將造成使用者對各個工具職責理解上的混亂。
我們將在本章中定義貫穿全書的術語和概念,而非提供一份統一的Docker百科全書。通常情況下,我們的定義與生態系統中的大體一致,但如果你所閱讀的博客文章中使用了不同的術語也不用太過驚訝。
在本章中,我們將介紹在生產環境中運行Docker的核心概念以及不涉及具體技術的容器常識。在隨后的章節中,我們將討論真實世界的生產環境用例,并詳細說明其組件和供應商信息。
下面讓我們來看一下本書所采用的Docker術語。
- 鏡像是指文件系統快照或tar包。
- 容器是指鏡像的運行態。
- 虛擬機持有整個操作系統和應用程序的快照。
- 虛擬機運行著自己的內核。
- 虛擬機可以運行Linux之外的其他操作系統。
- 容器只持有應用程序,不過應用程序的概念可以延伸到整個Linux發行版。
- 容器共享宿主機的內核。
- 容器只能運行Linux,不過在同一宿主機上運行的每個容器都可包含不同的發行版。
在應用程序新代碼提交或觸發其他條件時,系統自動構建新鏡像并進行部署。
設置/配備一臺物理服務器或虛擬機以便用于運行Docker容器的過程。
編排(orchestration,也稱編配)這個術語在Docker生態系統中有多種含義。通常情況下,它包括調度和集群管理,不過有時也包括了宿主機管理。
在本書中,我們將編排作為一個松散的總稱,包括容器調度的過程、集群的管理、容器的鏈接(發現),以及網絡流量路由。或者換句話說,編排是個控制器進程,用于決定在哪里運行容器,以及如何讓集群知道可用的服務。
用于決定哪些容器可以以給定的資源約束(如CPU、內存和IO)運行在哪些宿主機上。
容器如何公開服務給集群,以及發現如何查找其他服務并與之通信的過程。舉個簡單的用例:一個網站應用容器發現如何連接到數據庫服務。
Docker文檔中的發現是指將容器鏈接在一起,不過在生產級系統中,通常使用的是更復雜的發現機制。
配置管理過去常常指的是Docker出現之前的自動化工具,如Chef和Puppet。大多數的DevOps團隊正在轉移到Docker上,以消除這類配置管理系統的復雜度。
在本書的示例中,配置管理工具只用于配備具有Docker和少量其他東西的宿主機。
本書著重于生產環境或非開發環境中的Docker,這意味著我們不會花太多的篇幅在開發環境中Docker的配置和運行上。但由于所有服務器都在運行代碼,如何看待在Docker和非Docker系統中的應用程序代碼還是值得簡單討論一下的。
與Chef、Puppet和Ansible這類傳統配置系統不同,Docker最好的使用方式是將應用程序代碼預先打包成一個Docker鏡像。鏡像通常包含所有的應用程序代碼、運行時的依賴以及系統的需求。而包含數據庫憑證和其他敏感信息的配置文件通常在運行時添加,而非內建到鏡像中。
有些團隊會在開發機上手工構建Docker鏡像,然后推送到鏡像倉庫,之后再從倉庫中拉取鏡像到生產環境宿主機中。這是個很簡單的用例。雖然行得通,但從工作流和安全角度考慮并不理想。
一個更常見的生產環境示例是,使用持續集成/持續交付系統在應用程序代碼或Dockerfile文件發生變更時自動構建新鏡像。
過去的幾年時間,科技發生了巨大變化,從物理服務器到虛擬服務器,再到擁有PaaS環境的云計算。不論是否采用了全新架構,Docker鏡像都可以在當前環境中很容易地被使用。要使用Docker,并不需要立即從單體應用程序遷移到面向服務架構。有很多用例允許在不同層次上集成Docker。
Docker常用于以下場景。
- 使用以鏡像為基礎的部署方式取代類似Capistrano的代碼部署系統。
- 安全地在同一臺服務器中運行遺留應用和新應用。
- 使用一個工具鏈循序漸進地遷移到面向服務架構。
- 管理云端或裸機上的水平擴展性和彈性。
- 確保從開發環境到預演環境到生產環境跨環境的一致性。
- 簡化開發人員的機器設置和一致性。
將應用的后臺程序遷移到Docker集群中,同時保持網頁服務器和數據庫服務器不變是開始使用Docker的常見示例。另一示例是將應用的部分REST API遷移到Docker中運行,前端使用Nginx代理在遺留服務和Docker集群之間路由通信。通過使用此類技術,團隊可以漸進式地從單體應用無縫地遷移到面向服務架構。
如今的應用程序往往需要幾十個第三方庫,用于加速功能開發或連接第三方SaaS和數據庫服務。每個庫都可能產生bug,或是讓用戶陷入版本依賴的泥沼。再加上庫的頻繁更改,要在基礎設施上完成工作代碼的持續部署而不引起失敗,壓力巨大。
Docker可貴的鏡像思想使得技術團隊在部署工作代碼時,不論是單體架構、面向服務或是二者的混合,由于代碼及其依賴項捆綁在同一個鏡像中,所使用的方式對每次部署都是可測試、可重復、文檔化且一致的。一旦一個鏡像構建完畢,就可以部署到任意多個運行著Docker守護進程的服務器上。
另外一個常見的Docker用例是跨環境部署一個單一容器,其典型的代碼路徑是從開發環境到預演環境再到生產環境。容器為整個代碼路徑提供了一個一致的、可測試的環境。
作為一個開發人員,Docker模型允許在其個人電腦上調試與生產環境完全一致的代碼。開發人員可以很容易地下載、運行和調試有問題的生產環境鏡像,且無需事先對本地開發環境進行修改。
在生產環境中運行Docker容器困難不小,但還是能實現的。每天都有越來越多公司開始在生產環境中運行Docker。如同所有的基礎設施一樣,我們建議以小規模入手,然后漸進式地完成遷移。
對生產環境有很多要求:安全可靠的部署、健康檢查、最小或零停機時間、從失敗中恢復的能力(回滾)、一個集中存儲日志的方式、一種分析或調試應用的方式,以及一種聚合監控參數的方式。類似Docker這樣的新技術雖然使用起來非常有趣,但還需要時間來完善。
Docker在可移植性、一致性以及打包具有眾多依賴的服務這些方面非常有優勢。多數團隊會因為以下一個或多個痛點而堅持使用Docker。
- 一個應用的不同部分使用大量不同的依賴。
- 支持使用舊依賴的遺留應用程序。
- 開發團隊與DevOps之間的工作流問題。
本書中我們所采訪的團隊,有一個共同的警示:切勿嘗試在一個組織內讓采用Docker這事一蹴而就。即便運維團隊已經為采用Docker做好了充分的準備,也請記住,過渡到Docker通常意味著將管理依賴的重任推給了開發人員。雖然很多開發人員都渴求這種自主權,以便加快迭代,但并非每位開發人員都有能力或興趣將其列入自己的責任范圍。為了能有一個良好的Docker工作流,還是需要花些時間來轉變企業文化。
在第2章中,我們將闡述Docker的技術棧。
- 版權信息
- 版權聲明
- 內容提要
- 對本書的贊譽
- 譯者介紹
- 前言
- 本書面向的讀者
- 誰真的在生產環境中使用Docker
- 為什么使用Docker
- 開發環境與生產環境
- 我們所說的“生產環境”
- 功能內置與組合工具
- 哪些東西不要Docker化
- 技術審稿人
- 第1章 入門
- 1.1 術語
- 1.1.1 鏡像與容器
- 1.1.2 容器與虛擬機
- 1.1.3 持續集成/持續交付
- 1.1.4 宿主機管理
- 1.1.5 編排
- 1.1.6 調度
- 1.1.7 發現
- 1.1.8 配置管理
- 1.2 從開發環境到生產環境
- 1.3 使用Docker的多種方式
- 1.4 可預期的情況
- 為什么Docker在生產環境如此困難
- 第2章 技術棧
- 2.1 構建系統
- 2.2 鏡像倉庫
- 2.3 宿主機管理
- 2.4 配置管理
- 2.5 部署
- 2.6 編排
- 第3章 示例:極簡環境
- 3.1 保持各部分的簡單
- 3.2 保持流程的簡單
- 3.3 系統細節
- 利用systemd
- 3.4 集群范圍的配置、通用配置及本地配置
- 3.5 部署服務
- 3.6 支撐服務
- 3.7 討論
- 3.8 未來
- 3.9 小結
- 第4章 示例:Web環境
- 4.1 編排
- 4.1.1 讓服務器上的Docker進入準備運行容器的狀態
- 4.1.2 讓容器運行
- 4.2 連網
- 4.3 數據存儲
- 4.4 日志
- 4.5 監控
- 4.6 無須擔心新依賴
- 4.7 零停機時間
- 4.8 服務回滾
- 4.9 小結
- 第5章 示例:Beanstalk環境
- 5.1 構建容器的過程
- 部署/更新容器的過程
- 5.2 日志
- 5.3 監控
- 5.4 安全
- 5.5 小結
- 第6章 安全
- 6.1 威脅模型
- 6.2 容器與安全性
- 6.3 內核更新
- 6.4 容器更新
- 6.5 suid及guid二進制文件
- 6.6 容器內的root
- 6.7 權能
- 6.8 seccomp
- 6.9 內核安全框架
- 6.10 資源限制及cgroup
- 6.11 ulimit
- 6.12 用戶命名空間
- 6.13 鏡像驗證
- 6.14 安全地運行Docker守護進程
- 6.15 監控
- 6.16 設備
- 6.17 掛載點
- 6.18 ssh
- 6.19 私鑰分發
- 6.20 位置
- 第7章 構建鏡像
- 7.1 此鏡像非彼鏡像
- 7.1.1 寫時復制與高效的鏡像存儲與分發
- 7.1.2 Docker對寫時復制的使用
- 7.2 鏡像構建基本原理
- 7.2.1 分層的文件系統和空間控管
- 7.2.2 保持鏡像小巧
- 7.2.3 讓鏡像可重用
- 7.2.4 在進程無法被配置時,通過環境變量讓鏡像可配置
- 7.2.5 讓鏡像在Docker變化時對自身進行重新配置
- 7.2.6 信任與鏡像
- 7.2.7 讓鏡像不可變
- 7.3 小結
- 第8章 存儲Docker鏡像
- 8.1 啟動并運行存儲的Docker鏡像
- 8.2 自動化構建
- 8.3 私有倉庫
- 8.4 私有registry的擴展
- 8.4.1 S3
- 8.4.2 本地存儲
- 8.4.3 對registry進行負載均衡
- 8.5 維護
- 8.6 對私有倉庫進行加固
- 8.6.1 SSL
- 8.6.2 認證
- 8.7 保存/載入
- 8.8 最大限度地減小鏡像體積
- 8.9 其他鏡像倉庫方案
- 第9章 CI/CD
- 9.1 讓所有人都進行鏡像構建與推送
- 9.2 在一個構建系統中構建所有鏡像
- 9.3 不要使用或禁止使用非標準做法
- 9.4 使用標準基礎鏡像
- 9.5 使用Docker進行集成測試
- 9.6 小結
- 第10章 配置管理
- 10.1 配置管理與容器
- 10.2 面向容器的配置管理
- 10.2.1 Chef
- 10.2.2 Ansible
- 10.2.3 Salt Stack
- 10.2.4 Puppet
- 10.3 小結
- 第11章 Docker存儲引擎
- 11.1 AUFS
- 11.2 DeviceMapper
- 11.3 BTRFS
- 11.4 OverlayFS
- 11.5 VFS
- 11.6 小結
- 第12章 Docker 網絡實現
- 12.1 網絡基礎知識
- 12.2 IP地址的分配
- 端口的分配
- 12.3 域名解析
- 12.4 服務發現
- 12.5 Docker高級網絡
- 12.6 IPv6
- 12.7 小結
- 第13章 調度
- 13.1 什么是調度
- 13.2 調度策略
- 13.3 Mesos
- 13.4 Kubernetes
- 13.5 OpenShift
- Red Hat公司首席工程師Clayton Coleman的想法
- 第14章 服務發現
- 14.1 DNS服務發現
- DNS服務器的重新發明
- 14.2 Zookeeper
- 14.3 基于Zookeeper的服務發現
- 14.4 etcd
- 基于etcd的服務發現
- 14.5 consul
- 14.5.1 基于consul的服務發現
- 14.5.2 registrator
- 14.6 Eureka
- 基于Eureka的服務發現
- 14.7 Smartstack
- 14.7.1 基于Smartstack的服務發現
- 14.7.2 Nerve
- 14.7.3 Synapse
- 14.8 nsqlookupd
- 14.9 小結
- 第15章 日志和監控
- 15.1 日志
- 15.1.1 Docker原生的日志支持
- 15.1.2 連接到Docker容器
- 15.1.3 將日志導出到宿主機
- 15.1.4 發送日志到集中式的日志平臺
- 15.1.5 在其他容器一側收集日志
- 15.2 監控
- 15.2.1 基于宿主機的監控
- 15.2.2 基于Docker守護進程的監控
- 15.2.3 基于容器的監控
- 15.3 小結
- DockOne社區簡介
- 看完了