├── .gitignore ├── LICENSE ├── README.md ├── SUMMARY.md ├── book.json ├── cni ├── cni.md ├── history.md ├── index.md ├── summary.md └── usage.md ├── images ├── 2-1.png ├── 2-2.png ├── 2-3.png ├── 4-1.png ├── 4-2.png ├── 4-3.png ├── 4-4.png ├── 4-5.png ├── 5-1.png ├── 5-2.png ├── 5-3.png ├── 6-1.png ├── 6-2.png ├── 7-1.png ├── 7-2.png ├── 7-3.png ├── 7-4.png ├── 7-5.png └── A-1.png ├── introduction ├── administrative-considerations.md ├── docker-networking-modes.md ├── index.md ├── single-host.md └── summary.md ├── kubernetes ├── Kubernetes.md ├── advanced-networking.md ├── index.md ├── ingress-egress.md ├── inter-pod-networking.md ├── intra-pod-networking.md ├── networking.md ├── service-discovery.md └── summary.md ├── motivation ├── container-networking-stack.md ├── go-all-in.md ├── go-cattle.md ├── index.md └── pets-cattle.md ├── multi-host ├── administrative-considerations.md ├── docker-networking.md ├── index.md ├── multi-host-networking.md ├── options.md └── summary.md ├── orchestration ├── Docker.md ├── Mesos.md ├── Nomad.md ├── community.md ├── index.md ├── scheduler.md └── summary.md ├── preface └── preface.md ├── references └── references.md └── service-discovery ├── challenge.md ├── index.md ├── load-balancing.md ├── summary.md └── technologies.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Node rules: 2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 3 | .grunt 4 | 5 | # VS code 6 | .DS_Store 7 | 8 | ## Dependency directory 9 | ## Commenting this out is preferred by some people, see 10 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git 11 | node_modules 12 | 13 | # Book build output 14 | _book 15 | 16 | # eBook build output 17 | *.epub 18 | *.mobi 19 | *.pdf 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Container-Networking 2 | [Container Networking(From Docker to Kubernetes)](https://www.nginx.com/resources/library/container-networking-docker-kubernetes/) 中文版 3 | 4 | * [前言](preface/preface.md) 5 | * [1. 本书的写作动机](motivation/motivation.md) 6 | * [1.1 “宠物模式” vs “牲畜模式"](motivation/pets-cattle.md) 7 | * [1.2 Go Cattle!](motivation/go-cattle.md) 8 | * [1.3 容器网络技术栈](motivation/container-networking-stack.md) 9 | * [1.4 我需要全盘押注容器吗?](motivation/go-all-in.md) 10 | * [2. 容器网络初步](introduction/index.md) 11 | * [2.1 单主机容器网络101](introduction/single-host.md) 12 | * [2.2 Docker网络模型](introduction/docker-networking-modes.md) 13 | * [2.3 网络管理考量](introduction/administrative-considerations.md) 14 | * [2.4 本章小结](introduction/summary.md) 15 | * [3. 跨主机网络](multi-host/index.md) 16 | * [3.1 多主机容器网络101](multi-host/multi-host-networking.md) 17 | * [3.2 多主机容器网络的选择](multi-host/options.md) 18 | * [3.3 Docker网络](multi-host/docker-networking.md) 19 | * [3.4 网络管理考量](multi-host/administrative-considerations.md) 20 | * [3.5 本章小结](multi-host/summary.md) 21 | * [4. 编排](orchestration/index.md) 22 | * [4.1 scheduler实际上是做什么的?](orchestration/scheduler.md) 23 | * [4.2 Docker](orchestration/Docker.md) 24 | * [4.3 Apache Mesos](orchestration/Mesos.md) 25 | * [4.4 Hashicorp Nomad](orchestration/Nomad.md) 26 | * [4.5 社区很重要!](orchestration/community.md) 27 | * [4.6 本章小结](orchestration/summary.md) 28 | * [5. 服务发现](service-discovery/index.md) 29 | * [5.1 挑战](service-discovery/challenge.md) 30 | * [5.2 技术](service-discovery/technologies.md) 31 | * [5.3 负载均衡](service-discovery/load-balancing.md) 32 | * [5.4 本章小结](service-discovery/summary.md) 33 | * [6. CNI(容器网络接口)](cni/index.md) 34 | * [6.1 历史](cni/history.md) 35 | * [6.2 规范和使用](cni/usage.md) 36 | * [6.3 容器运行时和插件](cni/cni.md) 37 | * [6.4 本章小结](cni/summary.md) 38 | * [7. Kubernetes网络](kubernetes/index.md) 39 | * [7.1 Kubernetes简介](kubernetes/Kubernetes.md) 40 | * [7.2 Kubernetes网络概述](kubernetes/networking.md) 41 | * [7.3 Pod内网络](kubernetes/intra-pod-networking.md) 42 | * [7.4 Pod间网络](kubernetes/inter-pod-networking.md) 43 | * [7.5 Kubernetes中的服务发现](kubernetes/service-discovery.md) 44 | * [7.6 Ingress与Egress](kubernetes/ingress-egress.md) 45 | * [7.7 Kubernetes 中网络的高级主题](kubernetes/advanced-networking.md) 46 | * [7.8 本章小结](kubernetes/summary.md) 47 | * [附录](references/references.md) 48 | 49 | ## 在线阅读 50 | 51 | 可以通过[GitBook](https://mozhuli.gitbooks.io/Container-Networking)或者[Github](https://github.com/mozhuli/Container-Networking/blob/master/SUMMARY.md)来在线阅读。 52 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Introduction](README.md) 4 | * [前言](preface/preface.md) 5 | * [1. 本书的写作动机](motivation/index.md) 6 | * [1.1 “宠物模式” vs “牲畜模式"](motivation/pets-cattle.md) 7 | * [1.2 Go Cattle!](motivation/go-cattle.md) 8 | * [1.3 容器网络技术栈](motivation/container-networking-stack.md) 9 | * [1.4 我需要全盘押注容器吗?](motivation/go-all-in.md) 10 | * [2. 容器网络初步](introduction/index.md) 11 | * [2.1 单主机容器网络101](introduction/single-host.md) 12 | * [2.2 Docker网络模型](introduction/docker-networking-modes.md) 13 | * [2.3 网络管理考量](introduction/administrative-considerations.md) 14 | * [2.4 本章小结](introduction/summary.md) 15 | * [3. 跨主机网络](multi-host/index.md) 16 | * [3.1 多主机容器网络101](multi-host/multi-host-networking.md) 17 | * [3.2 多主机容器网络的选择](multi-host/options.md) 18 | * [3.3 Docker网络](multi-host/docker-networking.md) 19 | * [3.4 网络管理考量](multi-host/administrative-considerations.md) 20 | * [3.5 本章小结](multi-host/summary.md) 21 | * [4. 编排](orchestration/index.md) 22 | * [4.1 scheduler实际上是做什么的?](orchestration/scheduler.md) 23 | * [4.2 Docker](orchestration/Docker.md) 24 | * [4.3 Apache Mesos](orchestration/Mesos.md) 25 | * [4.4 Hashicorp Nomad](orchestration/Nomad.md) 26 | * [4.5 社区很重要!](orchestration/community.md) 27 | * [4.6 本章小结](orchestration/summary.md) 28 | * [5. 服务发现](service-discovery/index.md) 29 | * [5.1 挑战](service-discovery/challenge.md) 30 | * [5.2 技术](service-discovery/technologies.md) 31 | * [5.3 负载均衡](service-discovery/load-balancing.md) 32 | * [5.4 本章小结](service-discovery/summary.md) 33 | * [6. CNI(容器网络接口)](cni/index.md) 34 | * [6.1 历史](cni/history.md) 35 | * [6.2 规范和使用](cni/usage.md) 36 | * [6.3 容器运行时和插件](cni/cni.md) 37 | * [6.4 本章小结](cni/summary.md) 38 | * [7. Kubernetes网络](kubernetes/index.md) 39 | * [7.1 Kubernetes简介](kubernetes/Kubernetes.md) 40 | * [7.2 Kubernetes网络概述](kubernetes/networking.md) 41 | * [7.3 Pod内网络](kubernetes/intra-pod-networking.md) 42 | * [7.4 Pod间网络](kubernetes/inter-pod-networking.md) 43 | * [7.5 Kubernetes中的服务发现](kubernetes/service-discovery.md) 44 | * [7.6 Ingress与Egress](kubernetes/ingress-egress.md) 45 | * [7.7 Kubernetes 中网络的高级主题](kubernetes/advanced-networking.md) 46 | * [7.8 本章小结](kubernetes/summary.md) 47 | * [附录](references/references.md) 48 | 49 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Container Networking(From Docker to Kubernetes)", 3 | "author": "mozhuli ", 4 | "gitbook": ">= 3.2.2", 5 | "language": "zh-cn", 6 | "plugins": [ 7 | "alerts", 8 | "mermaid", 9 | "github", 10 | "github-buttons", 11 | "page-treeview", 12 | "editlink", 13 | "-lunr", 14 | "-search", 15 | "theme-comscore", 16 | "splitter", 17 | "search-plus", 18 | "toggle-chapters" 19 | ], 20 | "pdf": { 21 | "fontSize": 18, 22 | "footerTemplate": null, 23 | "headerTemplate": null, 24 | "margin": { 25 | "bottom": 36, 26 | "left": 62, 27 | "right": 62, 28 | "top": 36 29 | }, 30 | "pageNumbers": false, 31 | "paperSize": "a4" 32 | }, 33 | "pluginsConfig": { 34 | "page-treeview": { 35 | "copyright": "Copyright © mozhuli", 36 | "minHeaderCount": "2", 37 | "minHeaderDeep": "2" 38 | }, 39 | "github-buttons": { 40 | "repo": "mozhuli/Container-Networking", 41 | "types": [ 42 | "star", 43 | "watch" 44 | ], 45 | "size": "small" 46 | }, 47 | "github": { 48 | "url": "https://github.com/mozhuli/Container-Networking" 49 | }, 50 | "editlink": { 51 | "base": "https://github.com/mozhuli/Container-Networking/blob/master/", 52 | "label": "编辑本页" 53 | } 54 | }, 55 | "generator": "site" 56 | } 57 | -------------------------------------------------------------------------------- /cni/cni.md: -------------------------------------------------------------------------------- 1 | # 6.3 容器运行时和插件 2 | 3 |   CNI附带了许多[内置的插件](https://github.com/containernetworking/plugins),例如loopback和vlan。还有很多可用的第三方CNI插件。以下是按字母顺序排列的比较常用的CNI插件: 4 | 5 | - [Amazon ECS CNI插件集合](https://github.com/aws/amazon-ecs-cni-plugins) 6 | 7 | 亚马逊ECS使用的CNI插件集合,用Elastic Network Interfaces(ENI)配置容器的网络命名空间。 8 | 9 | - [Bonding](https://github.com/intel/bond-cni) 10 | 11 | 英特尔开发的CNI插件,用于故障转移和云原生环境中构建高可用的网络。 12 | 13 | - [Calico](https://github.com/projectcalico/calico-cni) 14 | 15 | Project Calico的CNI网络插件。Project Calico管理的是一个扁平的3层网络,为每个工作负载分配一个完全可路由的IP地址。对于需要覆盖网络的环境,Calico使用IP-in-IP隧道或可以与其他覆盖网络([flannel](https://github.com/coreos/flannel))一起使用。 16 | 17 | - [Cilium](https://github.com/cilium/cilium) 18 | 19 | 基于BPF的解决方案,提供容器之间的网络连接,可以在3/4层提供网络和安全的网络服务以及在7层提供HTTP和gRPC等现代协议。 20 | 21 | - [CNI-Genie](https://github.com/Huawei-PaaS/CNI-Genie) 22 | 23 | 华为的通用CNI网络插件。 24 | 25 | - [Infoblox](https://github.com/infobloxopen/cni-infoblox) 26 | 27 | 一个CNI的IPAM插件,与Infoblox接口配合提供IP地址管理服务。 28 | 29 | - [Linen](https://github.com/John-Lin/linen-cni) 30 | 31 | 基于Open vSwitch的覆盖网络CNI插件。 32 | 33 | - [Multus](https://github.com/Intel-Corp/multus-cni) 34 | 35 | 英特尔开发的支持多CNI插件的插件。 36 | 37 | - [nuage](https://github.com/nuagenetworks/nuage-cni) 38 | 39 | 支持Kubernetes的网络策略的Nuage Networks SDN插件。 40 | 41 | - [Romana](https://github.com/romana/kube) 42 | 43 | 支持Kubernetes网络策略的3层CNI插件。 44 | 45 | - [Silk](https://github.com/cloudfoundry/silk) 46 | 47 | 受flannel启发,专为Cloud Foundry设计的CNI插件, 48 | 49 | - [Vhostuser](https://github.com/intel/vhost-user-net-plugin) 50 | 51 | 该插件与Open vSwitch和[OpenStack VPP](https://github.com/openstack/networking-vpp)以及Kubernetes中的Multus CNI插件一起运行,主要用于裸机容器部署。 52 | 53 | - [Weave](https://github.com/weaveworks/weave#weave-net) 54 | 55 | Weaveworks开发的CNI插件。 -------------------------------------------------------------------------------- /cni/history.md: -------------------------------------------------------------------------------- 1 | # 6.1 历史 2 | 3 |   CNI是CoreOS在它的容器运行时rkt环境中率先开发的,用于定义网络插件,容器运行时和编排系统之间的通用接口。[Docker最初计划支持它](https://github.com/containerd/containerd/issues/362),但随后提出了Docker专有的[libnetwork](https://github.com/docker/libnetwork)方法来实现容器网络连接。 4 | 5 |   CNI和libnetwork是在2015年4月至6月期间并行开发的,经过一番讨论后,Kubernetes社区决定[不采用libnetwork](https://kubernetes.io/blog/2016/01/why-kubernetes-doesnt-use-libnetwork),而是使用CNI。现在几乎所有除Docker Swarm之外的容器编排系统都使用CNI; 所有容器运行时都支持它,并且支持CNI标准的插件很多。 6 | 7 |   2017年5月,[CNCF接受CNI成为其下的一个顶级项目](https://containerjournal.com/2017/05/23/cncf-aims-make-container-network-interface-standard/)。 -------------------------------------------------------------------------------- /cni/index.md: -------------------------------------------------------------------------------- 1 | # 6. CNI(容器网络接口) 2 | 3 |   如图6-1所示,[容器网络接口(CNI)](https://github.com/containernetworking/cni)为容器和容器编排系统提供了一个面向插件的网络解决方案。它由用于编写插件的规范和在Linux容器中配置网络接口的库组成。 4 | 5 | ![图6-1 CNI插件](../images/6-1.png) 6 | 7 |   CNI规范是轻量级的; 它只规范了容器网络的连接,以及容器被删除时网络资源的回收。 8 | 9 |   在本书中,我们将重点介绍CNI,因为它是容器编排系统网络解决方案的事实标准,被所有主流编排系统(如Kubernetes,Mesos和Cloud Foundry)采用。如果您专门使用Docker Swarm,则需要使用Docker的libnetwork,并且可能需要阅读Lee Calcoted的题为“[The Container Networking Landscape: CNI from CoreOS and CNM from Docker](https://thenewstack.io/container-networking-landscape-cni-coreos-cnm-docker/)”的文章,该文章对比了CNI和Docker网络模型,并为您提供了一些指导。 -------------------------------------------------------------------------------- /cni/summary.md: -------------------------------------------------------------------------------- 1 | # 6.4 本章小结 2 | 3 |   本章,我们介绍了CNI插件,下章我们将进入Kubernetes及着重介绍其网络是如何工作的。CNI在Kubernetes的网络中扮演着重要角色,您也可以在[这里](https://kubernetes.io/docs/concepts/cluster-administration/network-plugins/#cni)查看官方文档。 -------------------------------------------------------------------------------- /cni/usage.md: -------------------------------------------------------------------------------- 1 | # 6.2 规范和使用 2 | 3 |   CNI除了CNI规范之外,在编写[0.3.1-dev版本](https://github.com/containernetworking/cni/blob/spec-v0.3.1/SPEC.md)时,CNI的[Github仓库](https://github.com/containernetworking/cni)还包含了用于将CNI集成到应用程序中的Go源代码库以及用于调试CNI插件的命令行工具。CNI的[插件仓库](https://github.com/containernetworking/plugins)还包含了编写插件的事例和用于创建新插件的模板。 4 | 5 |   在我们深入CNI的使用之前,让我们看看CNI中的两个重要的概念: 6 | 7 | - 容器 8 | 9 | 与Linux的网络命名空间同义。它对应的单元取决于容器运行时的具体实现(单个容器或pod)。 10 | 11 | - 网络 12 | 13 | 一组可独立寻址的实体,可以相互通信。这些实体可能是单独的容器,主机或其他网络设备,如路由器。 14 | 15 |   从宏观上,我们来看看CNI是如何工作的,如图6-2所示。首先,容器运行时需要一些配置并向插件发出命令。插件被调用并配置网络。 16 | 17 | ![图6-2 CNI宏观架构](../images/6-2.png) 18 | 19 | 因此,CNI在概念上允许您做的是将容器添加到一个网络或者将其从一个网络中删除。CNI的当前版本定义了以下操作: 20 | 21 | - 将容器添加到一个或多个网络 22 | 23 | - 从网络中删除容器 24 | 25 | - 报告CNI版本 26 | 27 |   为了使CNI插件能够向网络中添加容器,容器运行时必须首先为该容器创建一个新的网络命名空间,然后调用一个或多个定义的插件。网络配置采用JSON格式,并包含必要的字段,如名称和类型以及特定插件的特定字段。实际的命令(例如,ADD)作为一个名为CNI_COMMAND的环境变量传入。 28 | 29 | *CNI插件需要为网络接口分配IP地址并设置与其相关的网络路由。这给CNI插件带来了很大的灵活性,但也给它带来了很大的负担。为了适应这种情况,CNI定义了专门负责IP地址管理的插件(IPAM)* 30 | 31 |   让我们来看看一个具体的CNI命令: 32 | 33 | ```bash 34 | $ CNI_COMMAND=ADD \ 35 | CNI_CONTAINERID=875410a4c38d7 \ 36 | CNI_NETNS=/proc/1234/ns/net \ 37 | CNI_IFNAME=eth0 \ 38 | CNI_PATH=/opt/cni/bin \ 39 | someplugin < /etc/cni/net.d/someplugin.conf 40 | ``` 41 | 42 |   此示例显示了如何使用特定配置(someplugin.conf)将某个插件(someplugin)应用于给定容器(875410a4c38d7)。请注意,虽然最初所有配置参数都作为环境变量传入,但现在更多的是使用(JSON)配置文件。 43 | 44 |   您可以在Jon Langemak的博客文章中“[Understanding CNI](http://www.dasblinkenlichten.com/understanding-cni-container-networking-interface/)”中了解更多关于使用CNI的知识。 -------------------------------------------------------------------------------- /images/2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/2-1.png -------------------------------------------------------------------------------- /images/2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/2-2.png -------------------------------------------------------------------------------- /images/2-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/2-3.png -------------------------------------------------------------------------------- /images/4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/4-1.png -------------------------------------------------------------------------------- /images/4-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/4-2.png -------------------------------------------------------------------------------- /images/4-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/4-3.png -------------------------------------------------------------------------------- /images/4-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/4-4.png -------------------------------------------------------------------------------- /images/4-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/4-5.png -------------------------------------------------------------------------------- /images/5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/5-1.png -------------------------------------------------------------------------------- /images/5-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/5-2.png -------------------------------------------------------------------------------- /images/5-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/5-3.png -------------------------------------------------------------------------------- /images/6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/6-1.png -------------------------------------------------------------------------------- /images/6-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/6-2.png -------------------------------------------------------------------------------- /images/7-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/7-1.png -------------------------------------------------------------------------------- /images/7-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/7-2.png -------------------------------------------------------------------------------- /images/7-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/7-3.png -------------------------------------------------------------------------------- /images/7-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/7-4.png -------------------------------------------------------------------------------- /images/7-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/7-5.png -------------------------------------------------------------------------------- /images/A-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozhuli/Container-Networking/b220f4aa21900eeb68608e55ce158cbdd7725a1d/images/A-1.png -------------------------------------------------------------------------------- /introduction/administrative-considerations.md: -------------------------------------------------------------------------------- 1 | # 2.3 网络管理考量 2 | 3 |   现在我们将从网络管理角度简要讨论您应该注意的一些方面。大多数这些问题对于多主机部署同样重要: 4 | 5 | ## IP地址分配 6 | 7 |   当容器频繁创建、销毁时候,手动分配IP地址是不可持续的,桥接模式在一定程度上解决了这个问题。为了防止本地网络上的ARP冲突,Docker守护程序从分配的IP地址生成一个MAC地址。 8 | 9 | ## 管理端口 10 | 11 |   有两种管理端口的方法:固定端口分配或端口动态分配。对于桥接模式,Docker可以自动分配(UDP或TCP)端口,从而使其可路由。像Kubernetes这样的系统采用扁平的IP容器网络模式,不会遇到这个问题。 12 | 13 | ## 网络安全 14 | 15 |   开箱即用,Docker启用了[容器间通信](https://docs.docker.com/network/)(意味着缺省值为--icc=true)。这意味着主机上的容器可以互相通信而没有任何限制,这可能会导致拒绝服务攻击。此外,Docker通过--ip_forward和--iptables标志来控制容器间和容器与容器外的通信。一种好的做法是,您应该研究这些标志的默认设置,根据公司的实际安全策略在Docker守护程序中设置它们。 16 | 17 |   像[CRI-O](http://cri-o.io)这样的系统,使用的是容器运行时接口(CRI),没有像Docker这样有功能庞大的守护进程,像较于Docker,可能会暴露更小的攻击面。 18 | 19 |   另一个网络安全方面是线上加密,通常意味着[RFC 5246](https://tools.ietf.org/html/rfc5246)标准的TLS/SSL。 20 | -------------------------------------------------------------------------------- /introduction/docker-networking-modes.md: -------------------------------------------------------------------------------- 1 | # 2.2 Docker网络模型 2 | 3 | Docker提供了四种单主机联网模式: 4 | 5 | - 桥接(bridge)模式 6 | 7 |   通常用于在独立容器中运行的应用程序,这是默认的Docker网络模型。 8 | 9 | - 主机(Host)模式 10 | 11 |   也用于独立容器,共享主机的网络。 12 | 13 | - 容器模式 14 | 15 |   让您重用另一个容器的网络命名空间。Kubernetes中pod内容器就是使用此种模式。 16 | 17 | - none网络 18 | 19 |   禁用Docker端的网络支持,并允许您设置自定义网络。 20 | 21 |   现在我们将仔细研究这四种网络模式,并在本章结尾部分介绍一些网络管理方面的注意事项,包括IP/端口管理和安全性。 22 | 23 | ## 桥接网络模式 24 | 25 |   在这种模式下(参见图2-2),Docker守护进程创建了docker0,它是一个虚拟以太网网桥,它可以在连接到它的任何port之间自动转发数据包。 默认情况下,守护进程会通过创建一对对等的网络接口将主机上的所有容器连接到此网桥,将其中一个对等端分配为容器的eth0接口,并将另一个对等端放在主机的命名空间中;以及将专用IP范围内的一个子网分配给网桥。以下是使用桥接模式的示例: 26 | 27 | ```bash 28 | $ docker run -d -P --net=bridge nginx:1.9.1 29 | $ docker ps 30 | CONTAINER ID 31 | STATUS 32 | 17d447b7425d 33 | Up 18 seconds 0.0.0.0:49153->443/tcp, 34 | IMAGE COMMAND CREATED 35 | PORTS NAMES 36 | nginx:1.9.1 nginx -g 19 seconds ago 37 | 0.0.0.0:49154->80/tcp trusting_feynman 38 | ``` 39 | 40 | ***注意***:因为桥接模式是Docker的默认设置,所以你可以在上一个命令中使用`docker run -d -P nginx:1.9.1`。如果您不使用-P参数或`-p `,则IP数据包将不可路由到本主机之外的其他容器。 41 | 42 | ![图2-2 Docker桥接网络模式](../images/2-2.png) 43 | 44 | ## 主机网络模式 45 | 46 |   该模式有效地禁用了Docker容器的网络隔离特性。由于容器共享主机的网络命名空间,因此如果主机网络没有受到防火墙限制,它可能会直接暴露给公共网络。此外作为共享主机网络命名空间的后果,您需要以某种方式管理端口的分配。以下是主机网络模式的实例: 47 | 48 | ```bash 49 | $ docker run -d --net=host ubuntu:14.04 tail -f /dev/null 50 | $ ip addr | grep -A 2 eth0: 51 | 2: eth0: mtu 9001 qdisc mq state UP group 52 | default qlen 1000 53 | link/ether 06:58:2b:07:d5:f3 brd ff:ff:ff:ff:ff:ff 54 | inet **10.0.7.197**/22 brd 10.0.7.255 scope global dynamic eth0 55 | $ docker ps 56 | CONTAINER ID IMAGE COMMAND CREATED 57 | STATUS PORTS NAMES 58 | b44d7d5d3903 ubuntu:14.04 tail -f 2 seconds ago 59 | Up 2 seconds jovial_blackwell 60 | $ docker exec -it b44d7d5d3903 ip addr 61 | 2: eth0: mtu 9001 qdisc mq state UP group 62 | default qlen 1000 63 | link/ether 06:58:2b:07:d5:f3 brd ff:ff:ff:ff:ff:ff 64 | inet **10.0.7.197**/22 brd 10.0.7.255 scope global dynamic eth0 65 | 66 | // 我们可以看到容器具有与主机相同的IP地址,即10.0.7.197 67 | ``` 68 | 69 |   在图2-3中我们看到,当使用主机网络模式时,容器有效地继承了主机的IP地址。这种模式比桥接模式更快,因为没有路由开销,但它将容器直接暴露给公共网络,并会带来所有安全隐患。 70 | 71 | ![图2-3 Docker主机网络模式](../images/2-3.png) 72 | 73 | ## 容器网络模式 74 | 75 |   在这种模式下,您告诉Docker重用另一个容器的网络命名空间。一般来说,如果您想对网络栈进行细粒度的控制,此模式非常有用。 实际上,Kubernetes网络使用这种模式,您可以在第7章中阅读更多关于它的内容。 76 | 77 | ```bash 78 | $ docker run -d -P --net=bridge nginx:1.9.1 79 | $ docker ps 80 | CONTAINER ID IMAGE COMMAND CREATED STATUS 81 | PORTS NAMES 82 | eb19088be8a0 nginx:1.9.1 nginx -g 3 minutes ago Up 3 minutes 83 | 0.0.0.0:32769->80/tcp, 84 | 0.0.0.0:32768->443/tcp admiring_engelbart 85 | $ docker exec -it admiring_engelbart ip addr 86 | 8: eth0@if9: mtu 9001 qdisc noqueue state 87 | UP group default 88 | link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff 89 | inet **172.17.0.3**/16 scope global eth0 90 | $ docker run -it --net=container:admiring_engelbart ubuntu:14.04 ip addr 91 | ... 92 | 8: eth0@if9: mtu 9001 qdisc noqueue state 93 | UP group default 94 | link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff 95 | inet **172.17.0.3**/16 scope global eth0 96 | ``` 97 | 98 |   这个例子中的结果正是我们所期望的:以--net=container创建的第二个容器与第一个容器(即172.17.0.3)具有相同的IP地址。 99 | 100 | ## none网络模式 101 | 102 |   该模式将容器放入容器自己的网络命名空间中,但未对其进行配置。实际上,这会关闭网络通信,对于两种情况非常有用:对于不需要网络的容器(如批量作业写入磁盘卷),或者要设置自定义网络(请参见第3章)。下面none网络模式的使用: 103 | 104 | ```bash 105 | $ docker run -d -P --net=none nginx:1.9.1 106 | $ docker ps 107 | CONTAINER ID IMAGE 108 | STATUS PORTS 109 | d8c26d68037c nginx:1.9.1 110 | Up 2 minutes 111 | COMMAND CREATED 112 | NAMES 113 | nginx -g 2 minutes ago 114 | grave_perlman 115 | $ docker inspect d8c26d68037c | grep IPAddress 116 | "IPAddress": "", 117 | "SecondaryIPAddresses": null, 118 | ``` 119 | 120 |   您可以阅读关于网络的更多信息,并通过[Docker文档](https://docs.docker.com/network/)了解配置选项。 121 | -------------------------------------------------------------------------------- /introduction/index.md: -------------------------------------------------------------------------------- 1 | # 2. 容器网络初步 2 | 3 |   本章以Docker为例重点介绍单主机容器网络,以及容器网络管理方面的一些挑战,例如IP地址管理和安全考虑。 在第3章中,我们将讨论多主机场景。 4 | -------------------------------------------------------------------------------- /introduction/single-host.md: -------------------------------------------------------------------------------- 1 | # 2.1 单主机容器网络101 2 | 3 |   容器需要在主机之上运行。 这可以是物理机,例如本地数据中心中的物理机,也可以是虚拟机,无论是在本地还是在云中。 4 | 5 |   对于Docker容器,主机有一个守护进程和一个客户端运行,如图2-1所示,您可以拉取/推送镜像,启动,停止,暂停和检查容器。 请注意,现在大多数(如果不是全部的话)容器都符合[Open Container Initiative(OCI)](https://www.opencontainers.org)标准,并且Docker还有一些有趣的替代品,尤其是在Kubernetes的CRI标准下(例如Kata,pouch)。 6 | 7 | ![图2-1 简化的单主机Docker架构](../images/2-1.png) 8 | 9 |   主机和容器之间的关系是1:N。 这意味着一台主机通常会运行多个容器。 例如,[Facebook报告](https://www.youtube.com/watch?v=C_WuUgTqgOc)说,依赖于机器的强健程度,平均每个主机运行10到40个容器。 10 | 11 |   无论您是单主机部署还是使用一组机器,您都可能需要处理一些网络问题: 12 | 13 | - 对于单主机部署,您几乎总是需要连接到同一主机上的其他容器;例如,像WildFly这样的应用程序可能需要连接到数据库容器。 14 | 15 | - 在多主机部署中,您需要考虑两个方面:同一个主机内容器间的通信以及跨主机容器间的通信。 性能考虑和安全方面都是您的设计方案需要考虑的。 无论是单个主机容量不足,或高可用的原因,还是希望使用分布式系统(如Apache Spark或Apache Kafka),多主机部署通常都是必需的。 16 | 17 | ***分布式系统和数据局部性:*** 18 | 19 |   *使用分布式系统(用于计算或存储)的基本思想是受益于并行处理,通常与数据局部性相对应。就数据局部性而言,我的意思是将代码传送到数据所在的位置,而不是(传统的)其他方式。* 20 | 21 |   *此时你可以想一下:如果数据集大小在TB范围内,并且代码大小以MB为单位,那么在集群中移动代码比将所有数据传输到中央处理位置更有效。 除了能够并行处理事物之外,通常可以通过分布式系统获得容错能力,因为系统的某些部分可以或多或少独立地继续工作。* 22 | 23 |   简而言之,Docker网络是Docker原生提供的本地容器SDN解决方案。 24 | -------------------------------------------------------------------------------- /introduction/summary.md: -------------------------------------------------------------------------------- 1 | # 2.4 本章小结 2 | 3 |   在本章中,我们看看了四种基本的单主机Docker网络模式和相关的网络管理问题。现在您已经对单主机案例有了基本的了解,让我们进入下一章来看看更有趣的案例:多主机容器网络。 -------------------------------------------------------------------------------- /kubernetes/Kubernetes.md: -------------------------------------------------------------------------------- 1 | # 7.1 Kubernetes简介 2 | 3 |   Kubernetes是一款开源的容器编排系统。它源自谷歌内部的容器编排系统Borg所积累的十多年的经验。截至2018年初,Kubernetes被认为是容器编排领域事实上的行业标准,云原生领域的“Linux系统”。 4 | 5 |   *我认为有关Kubernetes的诞生至少有两个重要时刻。第一次是在2014年6月7日,Joe Beda在GitHub上的最初[commit](https://github.com/kubernetes/kubernetes/commit/2c4b3a562ce34cddc3f8218a2c4d11c7310e6d56),它标志着项目开源的开始。第二个阶段是在一年后的2015年7月20日,当时谷歌推出了Kubernetes 1.0,并宣布组建一个专门的组织[云原生计算基金会(CNCF)](https://www.cncf.io)来主持和管理Kubernetes。我有幸参加了发布会,我可以告诉你,这无疑是庆祝项目诞生的一种方式。* 6 | 7 |   Kubernetes的体系结构(图7-1)为许多工作负载提供支持,使您可以运行无状态以及有状态的容器化应用程序。您也可以启动伺服性服务,例如低延迟应用程序以及批处理作业。 8 | 9 | ![图7-1 Kubernetes架构](../images/7-1.png) 10 | 11 |   Kubernetes的调度单位是一个pod。本质上,这是一组紧密耦合的一个或多个容器,它们总是并置在一起(即作为一个单元安排在一个节点上)。可以通过replicas控制器声明式地声明和执行以pod副本为模板的多个实例。所有资源(如pods,deployments,或者services)的逻辑组织都是通过标签选择器进行的。 12 | 13 |   使用Kubernetes,您几乎总是可以选择使用某种开源或封闭源替代方法替换默认的实现,无论是DNS还是监控。Kubernetes具有高度的[可扩展性](https://kubernetes.io/docs/concepts/overview/extending/),从定义新的工作负载和资源类型到定制面向用户的部分都是可以的。 14 | 15 |   本章假定您对Kubernetes及其术语有所了解。如果您需要了解关于Kubernetes如何运作的知识,我建议您查阅官方文档中的[Concepts部分](https://kubernetes.io/docs/concepts/)或Brendan Burns,Kelsey Hightower和Joe Beda撰写的[Kubernetes Up and Running(O'Reilly)](http://shop.oreilly.com/product/0636920043874.do)。 -------------------------------------------------------------------------------- /kubernetes/advanced-networking.md: -------------------------------------------------------------------------------- 1 | # 7.7 Kubernetes 中网络的高级主题 2 | 3 |   下面我将介绍两个与Kubernetes网络相关的高级主题:网络策略和服务网格。 4 | 5 | ## Network Policies 6 | 7 |   Kubernetes中的[网络策略](https://kubernetes.io/docs/concepts/services-networking/network-policies/)允许您指定如何允许pod间彼此进行通信。Kubernetes 1.7及以上版本的网络策略被认为是稳定的,因此您可以在生产中使用它们。 8 | 9 |   我们来看看具体的一个例子。例如,假设您想禁止所有通往superprivate namespace中所有pod的流量。您可以为该namespace创建默认的Egress策略,如下例所示: 10 | 11 | ```yaml 12 | apiVersion: networking.k8s.io/v1 13 | kind: NetworkPolicy 14 | metadata: 15 | name: bydefaultnoegress 16 | namespace: superprivate 17 | spec: 18 | podSelector: {} 19 | policyTypes: 20 | - Egress 21 | ``` 22 | 23 |   请注意,不同的Kubernetes发行版在不同程度上支持网络策略:例如,在OpenShift中,它们作为一等公民受到支持,并且可以通过[redhat-cop/openshitoolkit](https://github.com/redhat-cop/openshift-toolkit/tree/master/networkpolicy) 找到一系列的示例。 24 | 25 |   如果您想了解更多关于如何使用网络策略的信息,请查看Ahmet Alp Balkan的实用且详尽的博客“[Securing Kubernetes Cluster Networking](https://ahmet.im/blog/kubernetes-network-policy/)”. 26 | 27 | ## Service Meshes 28 | 29 |   展望未来,您可以使用服务网格,例如下面所要讨论的两款服务网格方案。服务网格的想法是,开发人员不必把网络通信和控制的负担放到自己身上,而是将这些工作外包给服务网格。因此,您可以从流量控制,可观察性,安全性等方面受益,而无需对源代码进行任何的更改。是不是特别棒? 30 | 31 | ### Istio 32 | 33 |   [Istio](https://istio.io)是目前最流行的服务网格,可用于Kubernetes,但不完全如此。它使用Envoy作为默认数据平面,它自己主要侧重于控制平面方面。仅举几例功能,它支持监视(Prometheus),跟踪(Zipkin/Jaeger),断路器,路由,负载平衡,故障注入,重试,超时,镜像,访问控制和速率限制等。Istio需要将Envoy代理作为sidecar容器部署在您的pod中。你可以通过Christian Posta的文章了解更多关于Istio的信息:[Deep Dive Envoy and Istio Workshop](http://blog.christianposta.com/microservices/deep-dive-envoy-and-istio-workshop/)。 34 | 35 | ### Conduit 36 | 37 |   [Conduit](https://conduit.io)由作为数据平面(由Rust编写)的sidecar容器和管理这些代理的控制平面(用Go编写)组成,类似于Istio。在CNCF项目[Linkerd]之后,这是Buoyant关于服务网格思想的第二次迭代; 他们是这个领域的先锋,且在2016年建立了服务网格概念。通过Abhishek Tiwari的博客文章“[Getting started with Con‐ duit - lightweight service mesh for Kubernetes](https://abhishek-tiwari.com/getting-started-with-conduit-lightweight-service-mesh-for-kubernetes/)”了解更多信息。 38 | 39 |   在我们结束本章和本书之前还有一点需要注意:服务网格还是很新的,所以你将其用于生产环境之前三思而行。 -------------------------------------------------------------------------------- /kubernetes/index.md: -------------------------------------------------------------------------------- 1 | # 7. Kubernetes网络 2 | 3 |   本章首先会简要Kubernetes,然后向您介绍Kubernetes中hight-level的网络概念。接下来我们将深入探讨Kubernetes如何实现容器网络,存在哪些流量类型以及如何在群集内彼此访问服务,以及如何让流量进入您的Kubernetes群集或访问特定的服务。 -------------------------------------------------------------------------------- /kubernetes/ingress-egress.md: -------------------------------------------------------------------------------- 1 | # 7.6 Ingress与Egress 2 | 3 |   下面我们将看看流量如何进出Kubernetes集群,也称为南北向流量。 4 | 5 | ## Ingress 6 | 7 |   到目前为止,我们已经讨论了如何从群集内访问一个pod或service。从群集外部访问pod更具挑战性。Kubernetes旨在为服务提供高可用性,高性能负载平衡。 8 | 9 |   最初,在Kubernetes中,南北向流量的唯一可用的方案是NodePort,现在LoadBalancer和ExternalName这些[方案](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types)也可供您使用。对于第7层流量(即HTTP),Ingress提供了更便携的方案,作为beta功能被引入Kubernetes 1.2,您可以使用Ingress将流量从外部世界路由到集群中的服务。 10 | 11 |   Kubernetes中的[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)的工作原理如图7-5所示:在概念上,它被分成两个主要部分,Ingress资源对象和一个Ingress控制器。Ingress资源对象定义了如何路由到后端service,Ingress控制器监听apiserver的/ingresses端点,了解正在创建或删除的service。一旦service的状态发送变化,Ingress控制器配置路由,以便外部流量落在集群内部的特定service。 12 | 13 | ![图7-5 Ingress](../images/7-5.png) 14 | 15 |   以下示例展示了一个Ingress资源的具体示例,用于将myservice.example.com/somepath的请求路由到端口9876上名为service1的Kubernetes服务。 16 | 17 | ```yaml 18 | apiVersion: extensions/v1beta1 19 | kind: Ingress 20 | metadata: 21 | name: example-ingress 22 | spec: 23 | rules: 24 | - host: myservice.example.com 25 | http: 26 | paths: 27 | - path: /somepath 28 | backend: 29 | serviceName: service1 30 | servicePort: 9876 31 | ``` 32 | 33 |   现在,Ingress资源定义好了,但是没有Ingress控制器,是没有任何反应的 所以让我们部署一个Ingress控制器,这里我们使用Minikube。 34 | 35 | ```bash 36 | $ minikube addons enable ingress 37 | ``` 38 | 39 |   一旦您在Minikube上启用了Ingress,您应该会看到它在Minikube的附加组件列表中显示为已启用。一分钟左右后,两个新的pod将创建在kube-system namespace下。你现在可以使用ingress了,我们使用下面的yaml文件,它配置了一个NGINX web服务的路径。 40 | 41 | ```yaml 42 | $ cat nginx-ingress.yaml 43 | kind: Ingress 44 | apiVersion: extensions/v1beta1 45 | metadata: 46 | name: nginx-public 47 | annotations: 48 | ingress.kubernetes.io/rewrite-target: / 49 | spec: 50 | rules: 51 | - host: 52 | http: 53 | paths: 54 | - path: /web 55 | backend: 56 | serviceName: nginx 57 | servicePort: 80 58 | $ kubectl create -f nginx-ingress.yaml 59 | ``` 60 | 61 |   现在NGINX通过IP地址192.168.99.100(这是我的Minikube IP)可用,yaml定义了它应该通过/web路径显示。 62 | 63 |   请注意,Ingress控制器在技术上可以是任何能够进行反向代理的工具,但NGINX是最常用的。此外,Ingress还可以通过云厂商的负载均衡器(如亚马逊的[ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html))实施。 64 | 65 |   有关Ingress的更多详细信息,请阅读Mark Betz的文章“[Understanding Kubernetes Networking:Ingress](https://medium.com/google-cloud/understanding-kubernetes-networking-ingress-1bc341c84078)”,也可以查看[Kubernetes SIG Network针对此主题进行的调查结果](https://github.com/bowei/k8s-ingress-survey-2018)。 66 | 67 | ## Egress 68 | 69 |   在Ingress的情况下,我们将流量从集群外部路由到集群内的服务,在Egress的情况下,我们处理相反情况:pod中的应用如何调用集群外部API? 70 | 71 |   人们可能想要控制允许哪个pod与外部服务之间可以通信,并且最重要的是实施网络策略。请注意,默认情况下,pod中的所有容器都可以执行egress流量。这些网络策略可以使用Kubernetes中的networkpolicy进行实施,也可以通过部署服务网格(service mesh)来实施。 -------------------------------------------------------------------------------- /kubernetes/inter-pod-networking.md: -------------------------------------------------------------------------------- 1 | # 7.4 Pod间网络 2 | 3 |   在Kubernetes中,每个pod具有可路由的IP,允许pod跨集群节点进行通信而无需NAT,也无需管理端口分配。由于每个pod都获得真实的IP地址,因此pod间可以在不使用代理或转换(例如NAT)的情况下进行通信。pod可以使用端口通信,也可以不使用更高级的服务发现机制进行通信。 4 | 5 |   我们将pod间(也称为东西向流量)的通信分为两类: 6 | 7 | - pod可以直接与其他pod进行通信; 在这种情况下,请求通信的pod需要知道被请求pod的IP地址,并且有可能会重复此操作,因为”牲畜模式“。 8 | 9 | - 普遍地,pod通过service与其他pod进行通信。在这种情况下,该service提供了一个可以通过DNS发现的稳定的,虚拟IP地址。 10 | 11 |   当一个容器试图获取网络接口的地址时,它看到的IP是与pod中任何其他容器看到的是同一个IP; 每个pod都有一个其他pod可以找到和使用的IP地址。通过使IP地址和端口在Pod内外相同,Kubernetes在整个集群中创建了一个编排的地址空间。有关此主题的更多详细信息,另请参阅Mark Betz撰写的文章“[Understanding Kubernetes Networking: Pods](https://medium.com/google-cloud/understanding-kubernetes-networking-pods-7117dd28727)”。 12 | 13 |   现在我们来看看[service](https://kubernetes.io/docs/concepts/services-networking/service/),如图7-3所示。 14 | 15 | ![图7-3 Kubernetes中的service](../images/7-3.png) 16 | 17 |   service为一组pod提供稳定的虚拟IP(VIP)地址。虽然Pod是经常变化的(扩容,缩容等),但service允许客户端通过使用VIP可靠地发现并连接到在Pod中正在运行的容器。VIP中的“虚拟”意味着它不是连接到网络接口的实际IP地址; 它的目的纯粹是充当稳定的”前端“,将流量转发到一个或多个Pod,因为service后端的pod的IP地址可能会不断变化。 18 | 19 |   必须认识到VIP在网络堆栈中不存在的。例如,你不能ping它们。他们只是Kubernetes内部管理的实体。还要注意它的格式是IP:PORT,所以IP地址和端口一起构成了VIP。可以把VIP视为一种映射到实际IP地址的数据结构的索引。 20 | 21 |   如图7-3所示,使用VIP 10.104.58.143的服务将流量路由到其中一个容器172.17.0.3或172.17.0.4。这里需要注意的是service和pod的属于不同的子网,现在,你可能想知道这实际上是如何工作的? 22 | 23 |   您可以通过标签选择器指定service后端的一组pod,例如,spec.selector.app = someapp Kubernetes将创建一个service,该service的目标是带有标签app = someapp的所有pod。请注意,如果存在这样的选择器,那么对于每个目标Pod将创建一个Endpoint类型的子资源,并且如果不存在标签选择器,则不会创建Endpoint。例如,请参阅以下代码示例kubectl describe命令的输出。这种Endpoint也不是在所谓的[Headless的service](https://kubernetes.io/docs/concepts/services-networking/service/#headless-services)的情况下创建的,它允许您对IP管理和服务发现的发生进行很好的控制。 24 | 25 |   保持最新的VIP和pod之间的映射是kube-proxy的工作(另请参阅[kube-proxy文档](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/)),这是一个在kubernetes集群中的每个node节点上运行的进程。 26 | 27 |   kube-proxy进程查询apiserver以了解群集中新的service,并相应地更新节点的iptables规则,以提供必要的路由信息。要了解更多service如何工作,请查看[Kubernetes Services By Example](https://blog.openshift.com/kubernetes-services-by-example/)。 28 | 29 |   让我们动手看看service是如何工作的:假设有一个名为webserver的deployment(例如,执行kubectl run webserver --image nginx),您可以自动创建一个服务,如下所示: 30 | 31 | ```bash 32 | $ kubectl expose deployment/webserver --port 80 33 | service "webserver" exposed 34 | $ kubectl describe service/webserver 35 | Name: webserver 36 | Namespace: default 37 | Labels: run=webserver 38 | Annotations: 39 | Selector: run=webserver 40 | Type: ClusterIP 41 | IP: 10.104.58.143 42 | Port: 80/TCP 43 | TargetPort: 80/TCP 44 | Endpoints: 172.17.0.3:8080,172.17.0.4:8080 45 | Session Affinity: None 46 | Events: 47 | 48 | $ kubectl get service -l run=webserver 49 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 50 | webserver ClusterIP 10.104.58.143 80/TCP 1m 51 | ``` 52 | 53 |   我们可以看到service已经拥有了一个集群内部的IP(10.104.58.143),EXTERNAL-IP列告诉你这个服务只能在集群内部使用,也就是说,没有来自群集外部的流量可以访问此service。 54 | 55 |   在图7-4中,您可以在Kubernetes仪表板中看到该service。 56 | 57 | ![图7-4 Dashbord中的service](../images/7-4.png) -------------------------------------------------------------------------------- /kubernetes/intra-pod-networking.md: -------------------------------------------------------------------------------- 1 | # 7.3 Pod内网络 2 | 3 |   在一个pod内有一个所谓的基础设施容器(pause container)。这是kubelet启动的第一个容器,它获取Pod的IP并设置网络命名空间。然后,该pod中的所有其他容器将加入到pause容器的网络和IPC命名空间。infra容器启用桥接网络模式,并且该pod中的所有其他容器都通过容器模式加入pause容器的网络命令空间。在pause容器中运行的初始过程没有任何其他作用,除了提供命名空间给其他容器共享。如果pause容器退出,则Kubelet杀死pod中的所有容器,然后开始清理工作。 4 | 5 |   由于以上原因,一个pod中的所有容器都可以使用localhost(或IPv4中的127.0.0.1)相互通信。您自己负责确保pod中的容器在使用的端口方面不会相互冲突。还要注意,这也意味着减少了pod内容器之间的隔离; 然而,此处pod紧密耦合的设计在容器编排环境中是一种很好的设计。 6 | 7 |   如果您想了解更多关于pause容器的信息,请阅读Ian Lewis的[The Almighty Pause Container](https://www.ianlewis.org/en/almighty-pause-container)。 8 | -------------------------------------------------------------------------------- /kubernetes/networking.md: -------------------------------------------------------------------------------- 1 | # 7.2 Kubernetes网络概述 2 | 3 |   Kubernetes并没有规定一定使用某种网络解决方案,而只是陈述了三个基本[要求](https://kubernetes.io/docs/concepts/cluster-administration/networking/#kubernetes-model): 4 | 5 | - pod可以与所有其他pod通信而无需NAT。 6 | - 节点可以与所有pod进行通信(反之亦然),无需NAT。 7 | - 容器看到的自己的IP与其他容器看到的IP相同。 8 | 9 |   您如何满足这些要求取决于您。这意味着你有很多自由空间来实现Kubernetes的网络。然而,这也意味着Kubernetes本身只会提供这么多; 例如,它支持CNI(第6章),但它没有提供默认的SDN解决方案。 10 | 11 |   从网络流量角度来看,我们在Kubernet中区分了三种类型,如图7-2所示: 12 | 13 | - pod内网络 14 | 15 | 一个pod中的所有容器共享一个网络命名空间,通过localhost彼此可见。 16 | 17 | - pod间网络 18 | 19 | 支持两种类型的东西向流量:Pod可以直接与其他Pod进行通信,或者,最好是Pod可以通过service与其他Pod进行通信。 20 | 21 | - Ingress和Egress 22 | 23 | Ingress是指将来自外部用户或应用的流量路由到pod,egress指的是从pod调用外部API。 24 | 25 | ![图7-2 Kubernetes中的网络类型](../images/7-2.png) 26 | 27 |   Kubernetes要求每个pod在一个扁平的网络中且都有一个IP,并与整个网络中的其他节点和pod完全连接。在上下文命名,服务发现或端口分配,这种IP-per-pod模型为您提供了一种向后兼容的方式,使您可以将Pod与虚拟机或物理主机几乎完全相同对待。该模型允许从非云原生应用程序和环境更平滑地过渡到Kubernetes环境。 28 | -------------------------------------------------------------------------------- /kubernetes/service-discovery.md: -------------------------------------------------------------------------------- 1 | # 7.5 Kubernetes中的服务发现 2 | 3 |   现在让我们来谈谈如何在[Kubernetes中发现服务](https://kubernetes.io/docs/concepts/services-networking/service/#discovering-services)。从概念上讲,您可以使用以下两种内置发现机制之一: 4 | 5 | - 通过环境变量(有限) 6 | 7 | - [使用DNS](https://github.com/kubernetes/dns/blob/master/docs/specification.md),如果已经安装了相应的DNS组件 8 | 9 | ## 基于环境变量的服务发现 10 | 11 |   对于基于环境变量的服务发现方法,一个简单的示例可能类似于以下示例代码: 12 | 13 | ```bash 14 | $ kubectl run -it --rm jump --restart=Never \ 15 | --image=quay.io/mhausenblas/jump:v0.1 -- sh 16 | If you don't see a command prompt, try pressing enter. 17 | / # env 18 | HOSTNAME=jump 19 | WEBSERVER_SERVICE_HOST=10.104.58.143 20 | WEBSERVER_PORT=tcp://10.104.58.143:80 21 | WEBSERVER_SERVICE_PORT=80 22 | WEBSERVER_PORT_80_TCP_ADDR=10.104.58.143 23 | WEBSERVER_PORT_80_TCP_PORT=80 24 | WEBSERVER_PORT_80_TCP_PROTO=tcp 25 | WEBSERVER_PORT_80_TCP=tcp://10.104.58.143:80 26 | ... 27 | ``` 28 | 29 |   环境变量WEBSERVER_XXX为您提供可用于连接服务的IP地址和端口。例如,您可以在jump容器中执行`curl 10.104.58.143`,您应该看到NGINX欢迎页面。 30 | 31 |   环境变量的方式虽然方便,但请注意,通过环境变量进行发现具有一个根本性缺陷:您希望发现的任何服务必须在要发现它的pod之前创建,否则环境变量将不会由Kubernetes填充。幸运的是存在更好的方法:DNS。 32 | 33 | ## 基于DNS的服务发现 34 | 35 |   将像example.com这样的完全合格的域名([FQDN](https://en.wikipedia.org/wiki/Fully_qualified_domain_name))映射到IP地址(如123.4.5.66)是DNS设计的目标。 36 | 37 |   在自己开发Kubernetes发行版时,也就是将所有必需组件(如SDN或DNS等附加组件)自己组合起来,而不是使用来自[30多种认证了的Kubernetes产品](https://github.com/cncf/k8s-conformance/)。值得考虑DNS解决方案有:CNCF的项目[CoreDNS](https://coredns.io/plugins/kubernetes/),以及功能相对较少的[kube-dns组件](https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/dns)。 38 | 39 |   那么我们如何使用DNS在Kubernetes中进行服务发现呢?如果安装并启用了DNS组件,该DNS服务器在Kubernetes API上监视正在创建或删除的service,它为它观察的每个service创建一组DNS记录。 40 | 41 |   在下一个示例中,让我们使用上面的webserver服务,并假设它已在默认namespace中运行。对于此服务,应存在DNS记录webserver.default(FQDN为webserver.default.cluster.local)。 42 | 43 | ```bash 44 | $ kubectl run -it --rm jump --restart=Never \ 45 | --image=quay.io/mhausenblas/jump:v0.1 -- sh 46 | If you don't see a command prompt, try pressing enter. 47 | / # curl webserver.default 48 | 49 | 50 | 51 | Welcome to nginx! 52 | 59 | 60 | 61 |

Welcome to nginx!

62 |

If you see this page, the nginx web server is successfully installed and 63 | working. Further configuration is required.

64 |

For online documentation and support please refer to 65 | nginx.org.
66 | Commercial support is available at 67 | nginx.com.

68 |

Thank you for using nginx.

69 | 70 | ``` 71 | 72 |   同一namespace中的Pod可以通过其短名称webserver访问该服务,而其他namespace中的Pod必须将该名称限定为webserver.default。请注意,这些FQDN查找的结果是ClusterIP。此外,Kubernetes支持命名端口的DNS服务(SRV)记录。因此,如果我们的Webserver具有名为http协议类型为TCP的端口,则可以从同一namespace为_http._tcp.webserver发出DNS SRV查询以发现http的端口号。还要注意,service的虚拟IP是稳定的,所以DNS结果不需要被重新查询。 -------------------------------------------------------------------------------- /kubernetes/summary.md: -------------------------------------------------------------------------------- 1 | # 7.8 本章小结 2 | 3 |   在本章中,我们介绍了Kubernetes的网络,并展示了如何在各种配置中使用它。感谢您的阅读,如果您有反任何馈意见,请通过[Twitter](https://twitter.com/mhausenblas)与我们联系。 -------------------------------------------------------------------------------- /motivation/container-networking-stack.md: -------------------------------------------------------------------------------- 1 | # 1.3 容器网络技术栈 2 | 3 |   容器网络技术栈包含以下内容: 4 | 5 | ## 低层网络层 6 | 7 |   包括网络设备,iptables,路由,IPVLAN和Linux命名空间。除非你从事容器网络相关的工作,否则通常不需要知道该层的细节,但至少应该知道这一点。请注意,这里的技术已经存在并被使用了十年以上。 8 | 9 | ## 容器网络层 10 | 11 |   该层提供了一些抽象,如单主机桥接网络模式和多主机IP-per-container解决方案。我将在第2章和第3章中介绍了这一层。 12 | 13 | ## 容器编排层 14 | 15 |   在这里,容器调度程序在调度容器的时候需要由较低层提供部分网络信息。在第4章中,我们将简要介绍下容器编排系统,在第5章中我们将重点讨论服务发现方面的内容。第6章讨论容器网络标准CNI,最后在第7章讨论Kubernetes网络。 16 | 17 | ***软件定义网络*** 18 | 19 |   *SDN实际上是一个营销术语。采用SDN,网络管理团队变得更加敏捷,并且可以对不断变化的业务需求做出更快的反应。 SDN是使用软件对网络进行配置,无论是通过API补充[网络功能虚拟化](https://en.wikipedia.org/wiki/Network_function_virtualization)还是通过软件构建网络。特别是如果您是开发人员或架构师,我建议您快速浏览思科对此主题的[精彩概述](https://www.cisco.com/web/solutions/trends/sdn/index.html)以及SDxCentral的文章“[什么是软件定义的网络(SDN)](https://www.sdxcentral.com/sdn/definitions/what-the-definition-of-software-defined-networking-sdn/)?”* 20 | 21 |   如果你在网络运维团队,那么你可能很乐意马上阅读下一章。 但是,如果您是架构师或开发人员,并且您的网络知识可能有点生疏,我建议在大概学习完[Linux网络管理员指南](http://www.tldp.org/LDP/nag2/nag2.pdf)之后进行下一步学习。 22 | -------------------------------------------------------------------------------- /motivation/go-all-in.md: -------------------------------------------------------------------------------- 1 | # 1.4 我需要全盘押注容器吗? 2 | 3 |   当我参加各种会议或用户组时,我常遇到因容器技术所带来的机遇而倍感兴奋的人。 与此同时,他们比较迷茫,需要对容器技术押注多大的砝码才能从中受益。 下表展示了我对目前业界使用容器技术情况的非正式概述,按照不同的阶段进行了分组: 4 | 5 | | 阶段 | 典型的配置 | 例子 | 6 | | :---: | :----: | :----: | 7 | | 传统 | 物理机或虚拟机,无容器 | 目前大多数产品的部署方式 | 8 | | 简单使用 | 用于应用程序依赖管理而手动启动容器 | 开发和测试环境 | 9 | | 定制化 | 用于管理容器而自定义的本地调度程序 | RelateIQ, Uber | 10 | | 全面爆发 | 使用第4章中的调度程序来管理容器,容错,自我修复 | Google, Zulily, Gutefrage.de | 11 | 12 |   请注意,全面爆发阶段不一定与部署的规模相符。 例如,Gutefrage.de只有6个裸机服务器在管理,但使用Apache Mesos来管理它们,并且您可以[在Raspberry Pi上轻松运行Kubernetes集群](https://www.hanselman.com/blog/HowToBuildAKubernetesClusterWithARMRaspberryPiThenRunNETCoreOnOpenFaas.aspx)。 13 | 14 |   到目前为止,您可能已经意识到我们正在处理分布式系统。 鉴于我们通常希望将容器部署到计算机网络中,我强烈建议您阅读[分布式计算的谬论](https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing)。 15 | 16 |   现在让我们一起继续深入容器网络. 17 | -------------------------------------------------------------------------------- /motivation/go-cattle.md: -------------------------------------------------------------------------------- 1 | # 1.2 Go Cattle! 2 | 3 |   将“牲畜模式"应用于基础架构中的美妙之处在于,它允许您扩展硬件(甚至是异构硬件。 例如,请参见Thorvald Natvig在Velocity 2015上的演讲:[数据中心的具有挑战性的基本假设:从硬件解耦基础设施](https://conferences.oreilly.com/velocity/devops-web-performance-ny-2015/public/schedule/detail/43771)”。) 4 | 5 |   它为混合云带来了弹性。 6 | 7 |   最重要的是,从运维人员的角度来看,“牲畜模式"可以让您获得体面的夜间睡眠,因为您将不需要在凌晨3点进行分页,只是为了更换损坏的硬盘驱动器或在不同的服务器上重新启动挂起的应用程序就像“宠物模式"那样。 8 | 9 |   然而,“牲畜模式"带来了一些挑战: 10 | 11 | - 非技术挑战 12 | 13 |   我敢说大部分挑战都是非技术性的,我如何说服我的经理? 我如何说服的CTO采取这种模式? 我的同事们是否会反对这种新的做事方式? 这是否意味着我们将需要更少的人来管理我们的基础设施? 本书中我不会为这些问题提供现成的解决方案; 相反,你可以去购买由Gene Kim,Kevin Behr和George Spafford(O'Reilly)撰写的[The Phoenix Project](http://shop.oreilly.com/product/9780988262508.do),它应该可以帮助你找到答案。 14 | 15 | - 技术挑战 16 | 17 |   技术挑战主要包括处理诸如机器的基本配置等问题,例如,使用Ansible来安装Kubernetes组件,如何建立容器之间和外部世界之间的通信链接,最重要的是,如何确保容器可自动部署和可发现的。 18 | 19 |   现在您已经了解“宠物模式” 与“牲畜模式"的异同,下节我将介绍整个容器网络技术栈。 20 | -------------------------------------------------------------------------------- /motivation/index.md: -------------------------------------------------------------------------------- 1 | # 1. 本书的写作动机 2 | 3 |   在本章中,我将向您介绍有关计算基础设施的“宠物模式” 和“牲畜模式"以及容器网络基本概念。如果您熟悉容器网路的基础知识,则可跳过本章。 4 | -------------------------------------------------------------------------------- /motivation/pets-cattle.md: -------------------------------------------------------------------------------- 1 | # 1.1 “宠物模式” vs “牲畜模式" 2 | 3 |   2012年2月,Randy Bias就[开放和可扩展云架构](https://www.slideshare.net/randybias/architectures-for-open-and-scalable-clouds)进行了有影响力的演讲。 在他的演讲中,他提出了“宠物模式”与“牲畜模式": 4 | 5 | - 宠物模式 6 | 7 |   您将机器视为个体。 您给每个(虚拟)机器一个名称,并且应用程序是静态地分配给机器。 例如,db-prod-2是数据库的生产服务器之一。 这些应用程序是手动部署的,当一台机器出现问题时,您需要手动将其重新部署到另一台机器上以恢复其到正常运行状态。 这种方法通常被认为是以前(非云原生)时代的主导范式。 8 | 9 | - 牲畜模式 10 | 11 |   您的机器是匿名的, 它们都是相同的(模硬件升级),它们有标号而不是名称,应用程序会自动部署到任何机器或者每台机器上。 当其中一台机器出现故障时,您不必立即担心;您可以在需要时替换它,或者只替换它的一部分。 12 | 13 |   尽管最初的“牲畜模式"主要用于在虚拟机上,但我们同样可以将“牲畜模式"应用于基础架构中。 14 | -------------------------------------------------------------------------------- /multi-host/administrative-considerations.md: -------------------------------------------------------------------------------- 1 | # 3.4 网络管理考量 2 | 3 |   在本章的最后一节中,我们将讨论您应该注意的一些网络管理方面的问题: 4 | 5 | ## IPVLAN 6 | 7 |   Linux内核版本[3.19](https://kernelnewbies.org/Linux_3.19)引入了IP-per-container功能。这为主机上的每个容器分配一个唯一且可路由的IP地址。IPVLAN使用单个的网络接口同时创建多个具有不同MAC地址的虚拟网络接口。 8 | 9 |   这项由Google的Mahesh Bandewar提供的[内核功能](https://github.com/torvalds/linux/blob/master/Documentation/networking/ipvlan.txt)在概念上类似于[macvlan驱动程序](http://backreference.org/2014/03/20/some-notes-on-macvlanmacvtap/),但IPVLAN更灵活,因为它在L2和L3上运行。 注意:此功能只支持Linux内核版本>3.19的内核。 10 | 11 | ## IP地址管理(IPAM) 12 | 13 |   多主机网络的关键挑战之一是如何将IP地址分配给集群中的每一个容器。有两种策略:1. 在现有的网络中找到实现它的方法;2. 跟现有网路正交,也就是实际上隐藏的网络层(即覆盖网络)。请注意,对于IPv6,第一种策略很轻松可以实现,因为找到一个空闲的地址空间应该容易得多。 14 | 15 | ## 编排工具兼容 16 | 17 |   本章讨论的许多多主机网络解决方案都是需要多组件的协同工作,包装Docker API并为您配置网络。所以在您选择具体网络方案之前,您应该确保检查您使用的容器编排工具是否存在任何兼容性的问题。在第4章中我们将详细谈论此类问题。 18 | 19 | ## IPv4 vs IPv6 20 | 21 |   到目前为止,大多数Docker部署都使用标准的IPv4,但IPv6有一定的吸引力。自2015年2月发布v1.5以来,Docker已经支持IPv6; 然而,Kubernetes的IPv6支持尚未完成。IPv4不断增长的地址短缺问题可能会鼓励更多的IPv6部署,也会摆脱网络地址转换(NAT),但尚不清楚究竟何时会达到临界点。 22 | -------------------------------------------------------------------------------- /multi-host/docker-networking.md: -------------------------------------------------------------------------------- 1 | # 3.3 Docker网络 2 | 3 |   在Docker 1.9版本引入了一个新的[docker network命令](https://blog.docker.com/2015/11/docker-multi-host-networking-ga/)。有了这个命令,Docker容器可以动态地连接到其他网络,每个网络可能由不同的网络驱动程序支持。 4 | 2015年3月,Docker Inc.[收购](https://www.networkworld.com/article/2893325/sdn/docker-buys-sdn-start-up-for-container-networking.html)了SDN创业公司SocketPlane,并将其产品重新命名为[Overlay Driver](https://blog.docker.com/2015/06/networking-receives-an-upgrade/)。自从Docker 1.9以来,这是多主机网络的默认设置。Overlay Driver通过[点对点通信](https://www.serf.io)扩展了常规网桥模式,并使用可插拔的键值存储后端来存储群集的状态信息,支持Consul,etcd和ZooKeeper。 5 | 6 |   要了解更多信息,我建议阅读以下博客文章: 7 | 8 | - Aleksandr Tarasov的“[容器网络的辉煌与衰败](http://developerblog.info/2015/11/16/splendors-and-miseries-of-docker-network/)” 9 | 10 | - Project Calico的“[Docker 1.9 Includes Network Plugin Support and Calico Is Ready!](https://www.projectcalico.org/docker-libnetwork-is-almost-here-and-calico-is-ready/)” 11 | 12 | - Weaveworks的“[Life and Docker Networking – One Year On](https://www.weave.works/blog/docker-networking-1-9-weave-plugin/)” -------------------------------------------------------------------------------- /multi-host/index.md: -------------------------------------------------------------------------------- 1 | # 3. 跨主机网络 2 | 3 |   如果您只在一台主机上使用容器,第2章介绍的技术就足够了。但是,如果单个主机的容量不足以处理您的工作负载,或者您希望获得更多弹性,则时候就需要横向扩展了。 -------------------------------------------------------------------------------- /multi-host/multi-host-networking.md: -------------------------------------------------------------------------------- 1 | # 3.1 多主机容器网络101 2 | 3 |   当进行水平扩展时,最终就会形成群集。这个时候就出现了许多问题:容器如何在不同主机上相互通信?您如何控制容器和集群外间的通信?如何保持状态(如IP地址分配)在群集中的一致性?与现有的网络基础设施的融合点在哪里?以及安全策略? 4 | 5 |   为了解决上述这些问题,我们将在本章的其余部分介绍多主机容器网络技术。由于不同的使用案例和环境具有不同的要求,因此我将不会针对不同网络方案的选择提供建议。您应针对自己的业务要求及网络环境进行权衡并作出明智的决定。 -------------------------------------------------------------------------------- /multi-host/options.md: -------------------------------------------------------------------------------- 1 | # 3.2 多主机容器网络的选择 2 | 3 |   Docker本身提供对覆盖网络的支持(基于主机间的底层网络而创建分布式网络)以及第三方提供商的网络插件。 4 | 5 |   实践中有多种多主机容器网络方案可选,特别是在Kubernetes环境中。主要包括如下多主机网络方案: 6 | 7 | ## Fannel 8 | 9 |   [Flannel](https://coreos.com/flannel/docs/latest/)是由CoreOS公司主导的一个虚拟网络方案,flannel为每个主机分配一个子网。在Kubernetes的环境下的每一个pod都有一个唯一的,可路由的IP。flannel支持一系列后端,例如VXLAN,AWS VPC和UDP。Flannel的优势在于它减少了端口映射的复杂性。例如,Red Hat公司的[Project Atomic](http://www.projectatomic.io)就是使用的[Flannel](https://twitter.com/ProjectAtomic/status/591231934505873408)。 10 | 11 | ## Weave Net 12 | 13 |   Weaveworks公司的[Weave网络](https://www.weave.works)也是创建了一个虚拟网络,多个主机上的Docker容器连接到此虚拟网络。应用程序使用此虚拟网络就好像容器都链接到同一个网络中的交换机一样,不需要配置端口映射和链接。无论这些容器运行在哪里,Weave网络上的应用程序容器提供的服务都可以被外界所访问。 14 | 15 |   同样,现有的内部系统可以暴露应用容器不管他们在哪里。Weave可以穿越防火墙并且支持部分连接;流量可以被加密,允许主机通过不可信网络连接。您可以通过Alvaro Saurin的文章“[Automating Weave Deployment on Docker Hosts with Weave Discovery](https://www.weave.works/blog/automating-weave-discovery-docker/)”了解Weave的服务发现功能。 16 | 17 |   如果你想尝试一下Weave,可以看看它的[Katacoda场景](https://katacoda.com/courses/weave)。 18 | 19 | ## Calico 20 | 21 |   Metaswitch的Calico项目使用标准的IP路由(准确地说,是[RFC 1105](https://tools.ietf.org/html/rfc1105)中定义的标准边界网关协议(BGP) 以提供3层网络解决方案。相比之下,大多数其他网络解决方案通过将第2层流量封装到更高层协议中来构建覆盖网络。 22 | 23 |   Calico的主要操作模式是不需要进行数据包的封装与解封装,专为可控制数据中心中的物理网络的公司所设计。 24 | 25 |   另外相近的另外一个项目[Canal](https://github.com/projectcalico/canal),它将Calico所具有的网络策略这一优势跟flannel的后端网络实现相结合。 26 | 27 | ## Open vSwitch 28 | 29 |   Open vSwitch是一款多层虚拟交换机,旨在通过编程扩展实现网络的自动化,同时支持标准管理接口和协议,如NetFlow,IPFIX,LACP和802.1ag。此外,它旨在支持跨多个物理服务器进行数据分发,目前用于Red Hat的Kubernetes发行版[OpenShift](https://www.openshift.org)中,同时也是Xen,KVM,Proxmox VE和VirtualBox中的默认的虚拟交换机。它也被集成到许多私有云系统中,例如OpenStack和oVirt。 30 | 31 | ## OpenVPN 32 | 33 |   OpenVPN允许您使用TLS创建虚拟专用网络(VPN)。这些VPN也可以用于在公共互联网上安全地连接容器。如果你想尝试基于Docker的设置,我建议您看一下DigitalOcean的“[如何在Ubuntu 14.04的Docker容器中运行OpenVPN](https://www.digitalocean.com/community/tutorials/how-to-run-openvpn-in-a-docker-container-on-ubuntu-14-04)”演练教程。 34 | -------------------------------------------------------------------------------- /multi-host/summary.md: -------------------------------------------------------------------------------- 1 | # 3.5 本章小结 2 | 3 |   在本章中,我们回顾了多种多主机网络方案,并讨论了一些网络管理问题,如IPAM和编排。在此时刻,您应该对单主机和多主机容器网络及其挑战有深入的了解。下一章我们一起来看看容器编排,看看它如何依赖于网络以及容器编排工具如何与各种网络方案进行交互。 -------------------------------------------------------------------------------- /orchestration/Docker.md: -------------------------------------------------------------------------------- 1 | # 4.2 Docker 2 | 3 |   在编写本文时,Docker在分布式环境中使用所谓的swarm模式,而在Docker 1.12之前,使用了独立的Docker Swarm模型。我们将在这里进行讨论。 4 | 5 | ## Swarm模式 6 | 7 |   自Docker 1.12以来,[swarm模式](https://docs.docker.com/engine/swarm/)已与Docker Engine集成。嵌入在Docker Engine中的编排功能是使用[SwarmKit](https://github.com/docker/swarmkit/)构建的。 8 | 9 |   Docker中的Swarm由多个运行在swarm模式下的主机组成,充当manager和worker角色(主机可以是manager,worker或同时充当这两种角色)。想对于独立的容器,任务就是一个正在运行的容器,它是swarm服务的一部分,由swarm manager进行管理。Docker swarm模式中的服务定义为要在manager或worker上执行的任务。Docker的工作内容是维持所期望的状态; 例如,如果一个工作节点变得不可用,Docker会将这些任务调度到另一个主机上。 10 | 11 |   以swarm模式运行的Docker不会阻止您在组成群集的任何主机上运行独立的容器。独立容器和群集服务之间的本质区别是,只有群集管理员可以管理群集,而独立容器可以在任何主机上启动。 12 | 13 |   要详细了解Docker的swarm模式,请查看官方的“[Swarm模式入门](https://docs.docker.com/engine/swarm/swarm-tutorial/)”教程或在Katacoda上的“[Docker Orchestration - Swarm模式入门](https://katacoda.com/courses/docker/getting-started-with-swarm-mode)”在线进行实践。 14 | 15 | ## Docker Swarm 16 | 17 |   Docker历史上有一个名为[Docker Swarm](https://docs.docker.com/swarm/)的本地集群管理工具。Docker Swarm[基于Docker API构建的](https://www.slideshare.net/Docker/2015-dockercon-orchestrationsysadmins),其工作方式如下:有一个Swarm manager负责调度,以及负责本地资源管理的代理运行的每个主机上(图4-3)。 18 | 19 | ![图4-3 Docker Swarm架构,基于T-Labs演示[PPT](https://www.slideshare.net/snrism/swarm-container-cluster-service)](../images/4-3.png) 20 | 21 |   Docker Swarm支持不同的[存储后端](https://docs.docker.com/swarm/discovery/):etcd,Consul和ZooKeeper。您还可以使用静态文件通过Swarm捕获您的群集状态,最近引入了一个名为[wagl](http://ahmetb.github.io/wagl/)的基于DNS的Swarm服务发现工具。 -------------------------------------------------------------------------------- /orchestration/Mesos.md: -------------------------------------------------------------------------------- 1 | # 4.3 Apache Mesos 2 | 3 |   [Apache Mesos](http://mesos.apache.org)(图4-4)是一个通用的集群资源管理器,对于开发人员来说就像是抽象出来的一台巨大的计算机资源。 从某种意义上讲,Mesos就像是分布式操作系统的核心。因此,它永远不会被单独使用,而是总是与所谓的框架一起使用,例如Marathon(用于Web服务器等长时后台运行服务)或Chronos(用于批处理作业),或者大数据和快速数据框架(如Apache Spark或 Apache Cassandra)。 4 | 5 | ![图4-4 Apache Mesos架构](../images/4-4.png) 6 | 7 |   Mesos支持容器化的工作负载(即运行Docker容器)和简单的可执行文件(例如,用于无状态和有状态服务的bash脚本或Linux ELF格式的二进制文件)。 8 | 9 |   在下面的讨论中,我假设您熟悉Mesos及其相关术语。如果您是Mesos新手,我建议您阅读David Greenberg的图书[Building Applications on Mesos(O'Reilly)](http://shop.oreilly.com/product/0636920039952.do),它作为分布式应用程序开发人员的入门介绍特别有用。 10 | 11 |   Mesos网络的特点和能力主要取决于您所使用的Mesos容器: 12 | 13 | - 对于Mesos容器,有一些先决条件,比如需要使用Linux内核大于3.16的版本和并且安装了libnl。然后,您可以构建启用了网络隔离器的Mesos agent。在启动时,您可以使用类似下面的命令: 14 | 15 | ```bash 16 | $mesos-slave --containerizer=mesos 17 | --isolation=network/port_mapping 18 | --resources=ports:[31000-32000];ephemeral_ports:[33000-35000] 19 | ``` 20 | 21 | 上面这条命令将配置Mesos agent使用范围从31,000到32,000的非临时端口和从33,000到35,000范围内的临时端口。所有容器共享主机的IP,并且端口范围分布在这些容器上(目标端口和容器ID之间1:1的映射)。通过网络隔离器,您还可以进行性能限制,比如带宽限制;并且可以对每个容器执行网络流量的监控。参见Jie Yu在MesosCon 2015上的演讲“[Mesos中的每个容器网络监控和隔离](https://www.youtube.com/watch?v=ZA96g1M4v8Y)”了解更多关于这方面的内容。 22 | 23 | - 对于Docker容器,请参阅[第2章](../introduction/index.md)。 24 | 25 |   请注意,自0.23版开始,Mesos支持[IP-per-container](https://mesosphere.com/blog/ip-per-container-mesos/)。如果您想了解更多关于Mesos网络的信息,请查看MesosCon 2015上Christos Kozyrakis和Spike Curtis关于“[Mesos Networking](https://events.static.linuxfound.org/sites/events/files/slides/mesos-networking.mesoscon2015.pdf)”的演讲。 26 | 27 |   尽管服务发现不是Mesos的主要功能,但实际中经常使用Mesos特定的解决方案:Mesos-DNS(详见服务发现章节),同时还有许多新兴的解决方案,比如traefik(详见服务发现章节)。 28 | 29 |   *由于Mesos-DNS是Mesos推荐的默认服务发现机制,因此关注Mesos-DNS如何[表示任务](http://mesosphere.github.io/mesos-dns/docs/naming.html)是很重要的。例如,正在运行的任务可能具有(逻辑)服务名称webserver.marathon.mesos,您可以通过DNS SRV记录找到分配的端口。* 30 | 31 |   如果您想免费在线试用Mesos,可以使用Katacoda上的“[将容器部署到DC/OS](https://katacoda.com/courses/dcos/getting-started)”在线环境。 -------------------------------------------------------------------------------- /orchestration/Nomad.md: -------------------------------------------------------------------------------- 1 | # 4.4 Hashicorp Nomad 2 | 3 |   [Nomad](https://www.nomadproject.io)是研发Vagrant的HashiCorp公司所研发的集群调度工具。它于[2015年9月推出](https://news.ycombinator.com/item?id=10291777),主要关注简单易用。据报道,其[scheduler](https://www.nomadproject.io/docs/internals/scheduling.html)的设计灵感来自谷歌的omega,它借鉴了诸如具有集群的全局状态以及采用乐观的并发调度等概念。 4 | 5 |   Nomad拥有一个基于代理的[架构](https://www.nomadproject.io/docs/internals/architecture.html),具有一个可以承担不同角色的单一二进制文件,支持滚动升级以及驱逐节点进而重新调度等功能。Nomad对所有状态复制和调度都使用一致性协议,并使用gossip协议来管理服务器的地址以实现群集自治和多区域联合。 如图4-5中,您可以看到Nomad的架构: 6 | 7 | ![图4-4 Nomad架构](../images/4-5.png) 8 | 9 | - server端负责接受来自用户的作业,管理客户端和计算任务的调度。 10 | 11 | - 客户端(每个VM实例一个客户端)负责与作业中的任务或应用程序进行交互。他们以pull的方式工作; 也就是说,他们在服务器上注册,然后他们定期轮询它以观察待处理的工作。 12 | 13 |   Nomad中的[作业](https://www.nomadproject.io/docs/job-specification/index.html)采用名为HCL的HashiCorp专有格式或JSON定义,Nomad提供命令行界面以及HTTP API与服务器进程进行交互。Nomad将基础设施抽象为区域和数据中心。区域可能包含多个数据中心,具体取决于您在何种规模上运行。您可以将AWS,Azure或Google Cloud中的zone(比如us-central1-b)看作数据中心,region看做区域(比如us-central1)。 14 | 15 |   我假定您熟悉Nomad及其术语。如果不是的话,我建议你看看“[Nomad:一种分布式,乐观并发的调度器:Armon Dadgar,HashiCorp](https://www.youtube.com/watch?v=YTmtBi3uNVU)”,它是对Nomad的一个很好的介绍,以及[Nomad官方文档](https://www.nomadproject.io/docs/)。 16 | 17 |   要尝试下Nomad,可以使用HashiCorp的[UI演示](https://demo.nomadproject.io/ui/jobs)或者使用Katacoda上的“[Nomad介绍](https://katacoda.com/hashicorp/scenarios/nomad-introduction)”免费的在线环境。 18 | 19 |   Nomad配备了几个所谓的任务驱动程序, 从通用执行程序到java, 再到qemu,最后到docker。对于Nomad所要求的[docker驱动程序](https://www.nomadproject.io/docs/drivers/docker.html),在撰写本文时,Docker版本为1.10或更高版本中,使用端口绑定的方式来暴露Docker容器中服务。它为Docker提供了自动和手动端口映射方案。 20 | 21 |   有关网络功能的更多详细信息,例如映射端口和标签的使用,请参阅[文档](https://www.nomadproject.io/docs/jobspec/networking.html)。 22 | 23 |   在[v0.2](http://blog.xebia.com/scheduling-containers-and-more-with-nomad/)版本中,Nomad引入了基于Consul的服务发现机制(详见服务发现章节)。它包括健康检查,并假定在Nomad内部运行的任务也需要能够连接到Consul代理,Consul代理对使用桥接网络模式的容器环境提出了挑战。 -------------------------------------------------------------------------------- /orchestration/community.md: -------------------------------------------------------------------------------- 1 | # 4.5 社区很重要! 2 | 3 |   选择编排系统时需要考虑的一个重要方面那就是编排系统后面的社区。可以从以下几点进行考虑: 4 | 5 | - 社区的管理是否由正式的组织支持,如Apache软件基金会(ASF)或Linux基金会(LF)? 6 | 7 | - 邮件列表,IRC频道,bug/issue tracker, Git仓库(补丁或pr的数量)等方面看社区活跃程度如何? 8 | 9 | - 这个编排系统是由单个实体控制(或者隐式的)的吗? 例如,Nomad由HashiCorp控制,Apache Mesos主要是Mesosphere(以及某种程度上是Twitter)控制的。 10 | 11 | - 是否有多个独立的云服务商和channel的支持? 例如,您可以在许多[不同的环境中运行Kubernetes](https://blog.openshift.com/kubernetes-little-guide-install-options/),并可以从许多组织以及Slack,邮件列表或论坛上获得帮助。 12 | -------------------------------------------------------------------------------- /orchestration/index.md: -------------------------------------------------------------------------------- 1 | # 4. 编排 2 | 3 |   利用“牲畜模式”来管理基础架构,您不需要手动分配某些机器来运行应用程序。相反,您将利用编排系统来管理容器的生命周期。在图4-1中,您可以看到容器业务流程包含一系列功能,包括但不限于: 4 | 5 | - 组织原语:(如Kubernetes中的标签用于查询和分组容器) 6 | 7 | - 调度容器以在合适的主机上运行。 8 | 9 | - 自动健康检查:以确定容器是否存活,并准备好为流量提供服务并在必要时重新启动。 10 | 11 | - 自动调节(根据利用率或更高级别的指标增加或减少容器数量) 12 | 13 | - 升级策略,从滚动更新到更复杂的技术,如[A/B测试和金丝雀部署](http://blog.christianposta.com/deploy/blue-green-deployments-a-b-testing-and-canary-releases/) 14 | 15 | - 服务发现,以确定具体提供本次服务的一个容器,通常也包括DNS的支持 16 | 17 | ![图4-1 编配及其组成部分](../images/4-1.png) 18 | 19 |   配置升级功能(在节点上安装或升级本地操作系统或设置容器运行时)有时候被认为是编排的一部分,但不在本书的讨论范围之内。 20 | 21 |   服务发现(第5章详细介绍)和调度实际上是同一枚硬币的两面。调度程序决定容器在集群中的位置,并在`容器 - >位置`表单中为其他部分组件提供最新的映射关系。我们可以用各种方式表示映射,例如在etcd等分布式键值存储中,通过DNS或通过环境变量。 22 | 23 |   在本章中,我们将从以下容器编排解决方案的角度讨论网络和服务发现:Docker Swarm和swarm模式,Apache Mesos和HashiCorp Nomad。您的公司可能已经在使用这三种方案中的一个(我们将在第7章中详细介绍Kubernetes),因此,为了完整起见,这里还是值得探讨。尽管如此,截至2018年初,Kubernetes已经成为容器编排领域的事实标准。 24 | 25 |   *除了本章讨论的三种容器编排系统之外,还有其他(封闭源代码)解决方案可供您了解,其中包括Facebook的[Bistro](https://facebook.github.io/bistro/),以及像[Amazon ECS](https://aws.amazon.com/cn/ecs/features/)之类的托管的解决方案。* 26 |   *如果您想更全面地探讨分布式系统调度方面的主题,我建议您阅读Google关于[Borg](https://research.google.com/pubs/pub43438.html)和[Omega](https://research.google.com/pubs/pub41684.html)的研究论文* 27 | 28 |   然而,在我们深入到容器编排系统之前,让我们回顾一下调度器(编排系统的核心组件)在集容器化工作负载的情况下实际是怎么执行调度的。 -------------------------------------------------------------------------------- /orchestration/scheduler.md: -------------------------------------------------------------------------------- 1 | # 4.1 scheduler实际上是做什么的? 2 | 3 |   分布式系统的调度程序根据用户的请求应用容器调度到一台或多台可用的主机上。例如,用户可能请求运行100个应用程序实例,因此调度程序需要找到可用主机来运行这100个实例。 4 | 5 |   我们来看一个具体的例子。 在图4-2中,您可以看到用户请求在集群中运行三个应用程序实例。调度程序根据对集群状态的了解以决定容器实例的放置位置。群集状态可能包括机器的使用情况,成功启动应用程序所需的资源以及限制,例如仅在支持SSD的计算机上启动此应用程序。 6 | 7 | ![图4-2 分布式系统调度程序的行为](../images/4-2.png) 8 | 9 |   此外,在进行调度时,服务质量有时候也需要考虑在内; 有关更多详细信息,请参阅Michael Gasch的文章“[QoS,节点可分配和Kubernetes调度程序](https://embano1.github.io/post/sched-reconcile/)”。 10 | 11 |   如果您想了解更多有关在分布式系统中进行调度的内容,我建议您查看John Wilkes的一篇文章“[Google集群管理](https://www.infoq.com/presentations/cluster-management-google)”。 12 | -------------------------------------------------------------------------------- /orchestration/summary.md: -------------------------------------------------------------------------------- 1 | # 4.6 本章小结 2 | 3 |   截至2018年初,Kubernetes(我们将在第7章中讨论)可以被认为是事实上的容器编排领域的标准。所有主要的云提供商,包括Docker和DC/OS(Mesos)都支持Kubernetes。 4 | 5 |   接下来,我们将继续讨论服务发现,这是容器编排系统的重要组成部分。 -------------------------------------------------------------------------------- /preface/preface.md: -------------------------------------------------------------------------------- 1 | # 前言 2 | 3 |   当您开始构建您第一个容器化应用程序时,您肯定会对容器技术所带来的前所未有的体验感到兴奋:使用容器镜像, 容器技术可以轻松地在开发和生产环境中一致地运行程序而无需额外的工作,容器镜像的分发由容器镜像仓库统一进行管理。 4 | 5 |   如今,您会对容器技术所带来的体验感到十分满意:例如您可以轻易地将你的Python应用容器连接到另一个数据库容器(例如PostgreSQL);借助于编排工具,您可以不需要手动管理容器,所有管理工作由编排工具完成,例如编排工具负责检查容器是否仍在运行,如果没有,则会重新启动它们。 6 | 7 |   在这个时候,您可能会意识一个挑战,那就是容器网络。不幸的是,这个领域仍然在不断地演进中,而且目前关于容器网络较为系统全面的文档比较匮乏。幸运的是,互联网上有大量关于容器网络的文章,repository和实践分享,通过这本书,您可以比较系统全面深入了解容器网络同时方便地访问其中许多优秀的文章。 8 | 9 | ## 我为什么写这本书 10 | 11 |   我常想:如果有人写了一本为容器网络提供基本指导的书,为读者指出每个相关技术(如覆盖网络,容器网络接口(CNI)和负载平衡器)的正确方向那该是极棒的! 12 | 13 |   不曾想那个人竟然是我。 通过本书,我想向您介绍有关容器网络,容器编排和服务发现的挑战和可用解决方案的概述。 在本书中,我将首先提出以下三个观点: 14 | 15 | - 如果没有正确深入理解容器网络,那么在采用容器技术后您肯定会不止一天遇到有关容器网络的糟糕情况,正所谓千里之行始于足下。 16 | - 服务发现和容器编排是一枚硬币的两面。 17 | - 容器网络和相应的服务发现技术领域仍然是比较年轻的:您可能会发现自己刚开始使用一套技术,然后新的技术就出现了并不得不尝试新的技术。 别担心,在容器技术领域这是正常的。 18 | 19 | ## 本书的目标读者 20 | 21 |   如果您是以下其中的某类读者群体,您将会发现该书很有用: 22 | 23 | - 容器软件开发人员 24 | - 网络运维人员 25 | - 渴望学习容器技术的SRE(网站可靠性工程师) 26 | - 想把现有工作负载迁移到容器环境的软件架构师 27 | 28 |   最后,分布式应用程序开发人员和后端工程师也应该能够从中得到收获。 29 | 30 |   请注意,这不是一本实操手册。 除了第2章中的一些Docker网络工具以及第7章中关于Kubernetes的一些资料之外,我没有展示更多的命令或源代码。 考虑这本书更像是一本指南(一本有大量注释的书签收藏夹), 希望它能帮你做出明智的决策在您进行容器化应用改造的时候。 31 | 32 | ## 个人简介 33 | 34 |   我目前就职于Red Hat的OpenShift团队,在那里我帮助他们充分利用软件。 我主要关注于容器技术的上游Kubernetes社区中,例如Autoscaling,Cluster Lifecycle和Apps 等特别兴趣小组(SIG)。 35 | 36 |   在2017年初加入Red Hat之前,我曾在Mesosphere工作过两年,在那里我也做过容器。我还拥有数据工程背景,曾在Mesosphere之前担任过MapR公司的首席数据工程师,主要负责分布式查询引擎,数据存储以及构建数据管道等工作。 37 | 38 |   最后,我是一位实用主义者,并且在整本书中竭尽全力确保对本书所讨论的技术不偏不倚。 39 | 40 | ## 致谢 41 | 42 |   首先非常感谢O'Reilly团队,尤其是Virginia Wilson。感谢您对本书第一版的指导和反馈(当时称为Docker网络与服务发现),该书于2015年发布,同时在本书的编写过程中您再次给予了我很大的支持与帮助。 43 | 44 |   非常感谢HashiCorp的Nic Jackson! 45 | 46 |   非常感谢Weaveworks的Bryan Boreham!您提供了超级宝贵的反馈意见,我很欣赏您关于流程的建议,您的勤勉,您对细节的关注,在我迷迷糊糊的时候或犯错时电话叫我出去放松。Bryan是一位容器网络网络专家,这也是本书在最终版本中读起来非常好的主要原因(我认为)。 47 | 48 |   最后但同样重要的是,我对给予我莫大支持的家庭表示最深切的感谢:我们的两个女儿Saphira和Ranya(他们的才能从Scratch编程到爱尔兰橄榄球),我们的儿子Iannis,还有我那个邪恶而又有趣的妻子Anneliese(我是否清空了洗衣机?不知道!)。 49 | -------------------------------------------------------------------------------- /references/references.md: -------------------------------------------------------------------------------- 1 | # 附录 2 | 3 |   深入了解一个领域,多阅读相关的资料是很好选择,在这里我已经汇集了一系列有关容器网络的资料链接,其中包含本书所涉及主题的深入分析等资料。但是,对于实操,我建议您查看Katacoda,这是一个免费的在线学习环境,其中包含从Docker到Kubernetes的100多种场景(请参阅图A-1中的屏幕截图)。 4 | 5 | ![图A-1 Dashbord中的service](../images/A-1.png) 6 | 7 |   您可以在任何浏览器中使用Katacoda; 会话通常在一小时后会终止。 8 | 9 | ## 容器网络 10 | 11 | ### Networking 101 12 | 13 | - “[Network Protocols](https://www.destroyallsoftware.com/compendium/network-protocols?share_key=97d3ba4c24d21147)” from the Programmer’s Compendium 14 | 15 | - “[Demystifying Container Networking](https://blog.mbrt.it/2017-10-01-demystifying-container-networking/)” by Michele Bertasi 16 | 17 | - “[An Empirical Study of Load Balancing Algorithms](http://liblb.com/learn.html)” by Khalid Lafi 18 | 19 | ### Linux Kernel and Low-Level Components 20 | 21 | - “[The History of Containers](https://rhelblog.redhat.com/2015/08/28/the-history-of-containers/)” by thildred 22 | 23 | - “[A History of Low-Level Linux Container Runtimes](https://opensource.com/article/18/1/history-low-level-container-runtimes)” by Daniel J. Walsh 24 | 25 | - “[Networking in Containers and Container Clusters](http://wiki.iptables.org/pablo/netdev0.1/papers/Networking-in-Containers-and-Container-Clusters.pdf)” by Victor Marmol, Rohit Jnagal, and Tim Hockin 26 | 27 | - “[Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic](https://www.slideshare.net/jpetazzo/anatomy-of-a-container-namespaces-cgroups-some-filesystem-magic-linuxcon)” by Jérôme Petazzoni 28 | 29 | - “[Network Namespaces](https://lwn.net/Articles/219794/)” by corbet 30 | 31 | - [Network classifier cgroup documentation](https://www.kernel.org/doc/Documentation/cgroup-v1/net_cls.txt) 32 | 33 | - “[Exploring LXC Networking](http://containerops.org/2013/11/19/lxc-networking/)” by Milos Gajdos 34 | 35 | ### Docker 36 | 37 | - [Docker networking overview](https://docs.docker.com/network/) 38 | 39 | - “[Concerning Containers’ Connections: On Docker Networking](https://www.linuxjournal.com/content/concerning-containers-connections-docker-networking)” by Federico Kereki 40 | 41 | - “[Unifying Docker Container and VM Networking](http://filipv.net/2015/11/06/unifying-docker-container-and-vm-networking/)” by Filip Verloy 42 | 43 | - “[The Tale of Two Container Networking Standards: CNM v. CNI](http://www.nuagenetworks.net/blog/container-networking-standards/)” by Harmeet Sahni 44 | 45 | ## Kubernetes网络 46 | 47 | ### Kubernetes Proper and Docs 48 | 49 | - [Kubernetes networking design](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/network/networking.md) 50 | 51 | - [Services](https://kubernetes.io/docs/concepts/services-networking/service/) 52 | 53 | - [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) 54 | 55 | - [Cluster Networking](https://kubernetes.io/docs/concepts/cluster-administration/networking/) 56 | 57 | - [Provide Load-Balanced Access to an Application in a Cluster](https://kubernetes.io/docs/tasks/access-application-cluster/load-balance-access-application-cluster/) 58 | 59 | - [Create an External Load Balancer](https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/) 60 | 61 | - [Kubernetes DNS example](https://github.com/kubernetes/examples/blob/master/staging/cluster-dns/README.md) 62 | 63 | - [Kubernetes issue 44063: Implement IPVS-based in-cluster service load balancing](https://github.com/kubernetes/kubernetes/issues/44063) 64 | 65 | - “[Data and analysis of the Kubernetes Ingress survey 2018](https://github.com/bowei/k8s-ingress-survey-2018)” by the Kubernetes SIG Network 66 | 67 | ### General Kubernetes Networking 68 | 69 | - “[Kubernetes Networking 101](https://www.slideshare.net/weaveworks/kubernetes-networking-78049891)” by Bryan Boreham of Weaveworks 70 | 71 | - “[An Illustrated Guide to Kubernetes Networking](https://speakerdeck.com/thockin/illustrated-guide-to-kubernetes-networking)” by Tim Hockin of Google 72 | 73 | - “[The Easy—Don’t Drive Yourself Crazy—Way to Kubernetes Networking](https://www.youtube.com/watch?v=H5Zl_kDOwBU)” by Gerard Hickey (KubeCon 2017, Austin) 74 | 75 | - “[Understanding Kubernetes Networking: Pods](https://medium.com/google-cloud/understanding-kubernetes-networking-pods-7117dd28727)”, “[Understanding Kubernetes Networking: Services](https://medium.com/google-cloud/understanding-kubernetes-networking-services-f0cb48e4cc82)”, and “[Understanding Kubernetes Networking: Ingress](https://medium.com/google-cloud/understanding-kubernetes-networking-ingress-1bc341c84078)” by Mark Betz 76 | 77 | - “[Understanding CNI (Container Networking Interface)](http://www.dasblinkenlichten.com/understanding-cni-container-networking-interface/)” by Jon Langemak 78 | 79 | - “[Operating a Kubernetes Network](https://jvns.ca/blog/2017/10/10/operating-a-kubernetes-network/)” by Julia Evans 80 | 81 | - “[nginxinc/kubernetes-ingress](https://github.com/nginxinc/kubernetes-ingress)” Git repo 82 | 83 | - “[The Service Mesh: Past, Present, and Future](https://www.youtube.com/watch?v=2trOvMUuLkk)” by William Morgan (KubeCon 2017, Austin) 84 | 85 | - “[Meet Bandaid, the Dropbox Service Proxy](https://blogs.dropbox.com/tech/2018/03/meet-bandaid-the-dropbox-service-proxy/)” by Dmitry Kopytkov and Patrick Lee 86 | 87 | - “[Kubernetes NodePort vs LoadBalancer vs Ingress? When Should I Use What?](https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0)” by Sandeep Dinesh 88 | -------------------------------------------------------------------------------- /service-discovery/challenge.md: -------------------------------------------------------------------------------- 1 | # 5.1 挑战 2 | 3 |   服务发现已经存在了一段时间(基本上,只要是分布式系统就需要服务发现)。 在容器环境中,服务发现的挑战归结为可靠地维护正在运行的容器与其位置之间的映射。容器的IP地址和可到达它的端口就是容器的位置。这种映射必须及时并准确地贯穿整个集群的容器的生命周期,包括重新启动。容器的服务发现需要解决如下两类问题: 4 | 5 | - 注册 6 | 7 |   建立`容器-->位置`映射。 因为只有调度容器的scheduler知道容器的位置,我们可以认为scheduler是有关容器位置的绝对真实的来源。 8 | 9 | - 查找 10 | 11 |   使其他服务或应用程序能够查找我们在注册阶段中存储的映射关系。有趣的属性包括信息的新鲜度和查询的延迟(avg,p50,p90等)。 12 | 13 |   让我们来看看查找阶段一些值得考虑的问题: 14 | 15 | - 如何排除不健康的主机或从查找路径中挂起容器?而不是简单地向某个方向发送请求。这同时也是跟负载平衡强烈相关话题,因为它非常重要,我们将在本章的最后一节详细讨论。 16 | 17 | - 服务发现具体实现中如何实现强一致性与高可用性。有人认为这是一个实现细节,有的人则认为[CAP定理](https://en.wikipedia.org/wiki/CAP_theorem)所要求的。 18 | 19 | - 可伸缩性也是需要考虑的问题。当然,如果你的集群规模很小,那么这里讨论的所有解决方案都是合适的。但是,如果您的群集有几百甚至几千个节点,那么在您承诺使用某项特定技术之前,您需要确保进行了适当的负载测试。 20 | 21 |   在本章中,您将了解服务发现方案的选择,在何处使用它们,怎样使用它们。 22 | 23 |   如果您想了解更多关于这个领域的需求和基本挑战,请阅读Jeff Lindsay的“[Docker环境下的现代服务发现](http://progrium.com/blog/2014/07/29/understanding-modern-service-discovery-with-docker/)”,并查看Shopify的Simon Eskildsen在最近的DockerCon上对[此主题](https://blog.codeship.com/dockercon-2015-resilient-routing-and-discovery-at-shopify/)的看法。 -------------------------------------------------------------------------------- /service-discovery/index.md: -------------------------------------------------------------------------------- 1 | # 5. 服务发现 2 | 3 |   采用"牲畜模式"管理基础设施带来的一个挑战那就是服务发现。“牲畜”模式中您需要平等对待所有的机器,并且您不会为某些应用程序手动分配某些机器; 相反,您可以将它留给一个软件(调度程序)来管理容器的生命周期。 4 | 5 |   那么问题来了,您如何知道您的容器最终被调度到哪个主机上了,以便您可以请求到它?这就是我们本章要讨论的服务发现。 -------------------------------------------------------------------------------- /service-discovery/load-balancing.md: -------------------------------------------------------------------------------- 1 | # 5.3 负载均衡 2 | 3 |   与服务发现密切相关的主题是负载均衡。通过负载均衡,您可以将负载(即入站服务请求)分散到多个容器中。在容器和微服务的环境中,负载平衡同时实现了几件事情: 4 | 5 | - 它可以使吞吐量最大化并缩短响应时间。 6 | 7 | - 它可以避免热点(即一个工作的容器过载)。 8 | 9 | - 它可以帮助过度激进的DNS缓存,例如Java中的缓存。 10 | 11 |   下面按照字母顺序列出了容器环境下流行的负载平衡方案: 12 | 13 | - [Bamboo](https://github.com/QubitProducts/bamboo) 14 | 15 |   守护进程自动配置HAProxy实例,部署在Apache Mesos和Marathon上。 请参阅p24e指南“[Service Discovery with Marathon, Bamboo and HAProxy](http://programmableinfrastructure.com/guides/service-discovery/bamboo-haproxy-marathon/)”了解具体的配置。 16 | 17 | - [Envoy](https://www.envoyproxy.io) 18 | 19 |   以C++编写的高性能分布式代理,最初是在Lyft中构建的。Envoy旨在用于单一服务和应用程序,并为服务网格提供通信总线和数据平面。这是[Istio](https://istio.io)的默认数据平面。 20 | 21 | - [Haproxy](http://www.haproxy.org) 22 | 23 |   稳定,成熟,经过生产检验的负责均衡解决方案。通常与NGINX一起使用。 24 | 25 | - [kube-proxy](https://kubernetes.io/docs/reference/generated/kube-proxy/) 26 | 27 |   在Kubernetes集群的每个节点上运行并更新服务IP。它支持简单的TCP/UDP转发和round-robin负载均衡。请注意,它仅用于集群内部的负载均衡,并且还用作服务发现的支持组件。 28 | 29 | - [Metallb](https://metallb.universe.tf) 30 | 31 |   针对裸金属Kubernetes集群的负载均衡实现,解决了Kubernetes不提供此类集群默认实现的事实。换句话说,您需要进入公共云环境才能从此功能中受益。请注意,为了使MetalLB能够工作,您可能需要一个或多个支持BGP协议的路由器。 32 | 33 | - [nginx](https://www.nginx.com/resources/admin-guide/load-balancer/) 34 | 35 |   这个领域的领先解决方案。借助NGINX,您可以获得循环,最少连接和ip散列等负载均衡策略的支持,以及即时配置,监控和许多其他重要功能。 36 | 37 | - [servicerouter.py](https://github.com/mesosphere/marathon-lb) 38 | 39 |   一个简单的脚本,用于从Marathon获取应用程序配置并更新HAProxy; 请参阅p24e指南“[Service Discovery with Marathon, Bamboo and HAProxy](http://programmableinfrastructure.com/guides/service-discovery/bamboo-haproxy-marathon/)” 40 | 41 | - [traefik](https://traefik.io) 42 | 43 |   这一类的后起之秀。Emile Vauge(traefik的首席开发人员)一定在做正确的事情。我非常喜欢它,因为它就像HAProxy一样,默认支持一些后端,如Marathon和Consul,开箱即用。 44 | 45 | - [Vamp-router](https://github.com/magneticio/vamp-router) 46 | 47 |   受Bamboo和Consul-HAProxy的启发,Magnetic.io写了Vamp-router,它支持通过REST API或ZooKeeper更新配置,路由和过滤器用于Canary发布和A/B测试以及ACL,并提供统计信息。 48 | 49 | - [Vulcand](http://vulcand.readthedocs.io/en/latest/) 50 | 51 |   受[Hystrix](https://github.com/Netflix/Hystrix)启发的HTTP API管理和微服务的反向代理。 52 | 53 |   如果您想了解更多关于负载均衡的信息,请查看Kevin Reedy在[nginx.conf 2014关于NGINX和Consul上的负载均衡的演讲](https://www.youtube.com/watch?v=A2NOziRYh7U)。 -------------------------------------------------------------------------------- /service-discovery/summary.md: -------------------------------------------------------------------------------- 1 | # 5.4 本章小结 2 | 3 |   为了结束本章,我已经整理了一张表格,概述了我们讨论过的服务发现解决方案。各种方案的最好选择取决于你的用例和要求。所以,把下面的表格作为一个快速的方向和总结。(另外,请注意,在Kubernetes的背景下,它是内置于系统中的): 4 | 5 | ![](../images/5-3.png) 6 | 7 | *由于容器领域的服务发现还处于快速成长的阶段,因此建议您不断重新评估您初始的选择,至少在服务发现的解决方案有巨大变化的时候* 8 | 9 |   在本章中,您了解了服务发现以及负载均衡。我们下章将开始讨论Kubernetes的相关内容,事实上的容器编排系统带有内置的服务发现功能(因此您不必担心本章中讨论的主题),并且有其独特的跨主机容器网络解决方案。 -------------------------------------------------------------------------------- /service-discovery/technologies.md: -------------------------------------------------------------------------------- 1 | # 5.2 技术 2 | 3 |   本节简要介绍各种服务发现技术,列出优点和缺点,并指出在互联网上对此的进一步讨论。如需更深入的了解,请查阅Adrian Mouat的书籍“[Using Docker](http://shop.oreilly.com/product/0636920035671.do)”(O'Reilly)。 4 | 5 | ## ZooKeeper 6 | 7 |   [Apache ZooKeeper](http://zookeeper.apache.org)是一个ASF基金会的top项目和基于JVM的集中式配置管理工具,提供与Google[Chubby](https://research.google.com/archive/chubby.html)相似的功能。ZooKeeper(ZK)将它的有效载荷数据按照文件系统的形式组织在一个所谓的znodes层次结构中。在集群中,leader被[选举](http://zookeeper.apache.org/doc/current/zookeeperInternals.html#sc_leaderElection)出来,客户端可以连接到任何服务器来检索数据。 您需要ZK群集中的2n + 1个节点。常见的配置是三个,五个或七个节点。除此之外,您需求在容错/吞吐量上进行折衷考虑。 8 | 9 |   ZooKeeper是经过生产验证,成熟且可扩展的解决方案,但它有一些使用方面的缺陷。有些人认为ZK集群的安装和管理是不太愉快的体验。我见过的大多数ZK的问题都来自某些服务(比如Apache Storm)滥用它。他们要么将太多的数据放入znode中,要么[读取/写入比例不健康](http://thelastpickle.com/blog/2012/01/12/ZooKeeper-Reading.html),本质上就是写得太快。如果您打算使用ZK,至少应考虑使用更高层的接口,如[Apache Curator](http://curator.apache.org)(这是一个围绕ZK进行大规模部署使用的包装库),以及Netflix的exhibitor(https://github.com/soabase/exhibitor)用于管理和监控ZK群集。 10 | 11 |   图5-1,您会看到两个组件:R/W(表示注册监视器,需要您自己编写代码)以及由R/W控制的HAProxy。无论何时在节点上调度容器时,它都会向ZK注册,使用/$nodeID/$containerID路径和IP地址作为其有效载荷数据的znode。R/W负责watch在这些znode上发生的变化并相应地配置HAProxy。 12 | 13 | ![图5-1 ZooKeeper设置服务发现示例](../images/5-1.png) 14 | 15 | ## etcd 16 | 17 |   [etcd](https://github.com/coreos/etcd)是CoreOS公司的一个产品, 它用Go语言编写。它是一个轻量级的分布式键值存储系统,它使用[Raft](https://raft.github.io)算法达成共识(leader–follower模型,leader选举)并使用复制日志方式将leader收到的信息分发给其follower。从某种意义上说,etcd在概念上与ZK很相似。虽然有效载荷数据可以是任意的,但etcd的HTTP API是基于JSON的,和ZK一样,您可以watch etcd中value的更改。etcd的一个非常有用的功能就是key上的TTL,这是服务发现的一个很好的构建块。与ZK相同,出于相同的原因,您需要在一个etcd群集中使用2n + 1个节点。 18 | 19 |   etcd的安全模型提供了TLS/SSL进行线上加密,客户端和集群之间以及etcd节点之间的客户端证书验证。 20 | 21 |   在图5-2中,您可以看到etcd服务发现设置与ZK的设置非常相似。主要区别在于使用confd配置HAProxy,而不是编写自己的脚本。 22 | 23 | ![图5-2 etcd设置服务发现示例](../images/5-2.png) 24 | 25 | ## Consul 26 | 27 |   [Consul](https://www.consul.io)使用Go语言编写,它由HashiCorp所研发。Consul提供了服务注册,服务发现和健康检查等功能。可以使用HTTP API或通过DNS查询服务。Consul支持多数据中心部署。 28 | 29 |   Consul的一个特点就是分布式键值存储,类似于etcd。它也使用了Raft一致性算法(对于2n + 1节点,同样适用于ZK和etcd),但是部署是不同的。Consul具有代理的概念,可以以两种可用模式之一运行:1.作为服务器(提供键值存储和DNS),2.作为客户端(注册服务和运行健康检查)。节点的服务发现由[Serf](https://www.serf.io)实现。 30 | 31 |   通过Consul,您基本上有四种选择来实现服务发现(从最理想到最不理想的顺序): 32 | 33 | 1. 使用[服务定义配置文件](https://www.consul.io/intro/getting-started/services.html),它由Consul的代理进行解释。 34 | 35 | 1. 使用具有Consul后端的工具,如[traefik](https://github.com/EmileVauge/traefik/blob/master/docs/index.md#consul)。 36 | 37 | 1. 编写你自己的sidekick进程,通过[HTTP API](https://www.consul.io/api/index.html)注册服务。 38 | 39 | 1. 利用HTTP API将服务注册服务内部中。 40 | 41 |   想要了解有关使用Consul进行服务发现的更多信息?可以查看Jeff Lindsay的文章“[Consul服务发现与Docker](http://progrium.com/blog/2014/08/20/consul-service-discovery-with-docker/)”和Joseph Miller的文章“[Docker DNS & Service Discovery with Consul and Registrator](http://artplustech.com/docker-consul-dns-registrator/)”。 42 | 43 | ## 完全基于DNS的解决方案 44 | 45 |   数十年来,DNS一直是互联网不可缺少的一部分。DNS系统的最终一致性,某些客户积极缓存DNS查找的事实,以及对SRV记录的依赖,使您可以考虑使用DNS进行服务发现。 46 | 47 |   我标题为“完全基于DNS的解决方案”,因为Consul技术上也有一个DNS服务器,但它只是您如何使用它来进行服务发现的一种选择。以下是一些流行且广泛使用的基于DNS的服务发现解决方案: 48 | 49 | - Mesos-DNS 50 | 51 |   [Mesos-DNS](http://mesosphere.github.io/mesos-dns/)专用于Apache Mesos中的服务发现。Go开发而成,Mesos-DNS为任何正在运行的任务轮询活动的Mesos主进程,并通过DNS以及HTTP API公开`:`信息。对于其他主机名或服务的DNS请求,Mesos-DNS可以使用外部nameserver,也可以利用现有的DNS服务器仅将Mesos任务的请求转发给Mesos-DNS。 52 | 53 | - SkyDNS 54 | 55 |   使用etcd,您可以向[SkyDNS](https://github.com/skynetservices/skydns)发布您的服务,SkyDNS将服务定义存储到etcd中并更新其DNS记录。您的客户端应用程序发出DNS查询以发现服务。因此,在功能方面,它与Consul很相似,没有健康检查。 56 | 57 | - WeaveDNS 58 | 59 |   在Weave 0.9中引入了[WeaveDNS](https://www.weave.works/docs/net/latest/tasks/weavedns/weavedns/),作为在Weave网络上服务发现的简单解决方案,允许容器通过主机名查找其他容器的IP地址。在Weave 1.1中,引入了一种所谓的[Gossip DNS](https://www.weave.works/blog/weave-gossip-dns/)协议,通过缓存提高了查找速度,并且包含了超时功能。在新的实现中,注册被广播给所有参与的实例,随后将所有条目保存在内存中,后续的请求就可以在本地进行处理查找。 60 | 61 | ## Airbnb的SmartStack和Netflix的Eureka 62 | 63 |   在本节中,我们将看看两个定制系统,这些系统是为满足特定需求而开发的。这并不意味着你不能或不应该使用它们,您可以从中借鉴一些经验。 64 | 65 |   Airbnb的[SmartStack](https://github.com/airbnb/smartstack-cookbook)是一个自动化的服务发现和注册框架,透明地处理创建,删除,失败和维护工作。SmartStack使用与您的容器在同一主机上运行的两个独立服务:Nerve(写入ZK)进行服务注册,Synapse(动态配置HAProxy)进行查找。对于非容器环境来说,这是一个行之有效的解决方案,对Docker环境是否有用,还需要时间检验。 66 | 67 |   Netflix的[Eureka](https://github.com/Netflix/eureka)不同,主要是因为它诞生于AWS环境(所有Netflix的服务跑着AWS上)。Eureka是一种基于REST的服务,用于定位服务以实现中间层服务器的负载平衡和故障转移,并且还提供了一个基于Java的客户端组件,该组件与服务进行直接交互。这个客户端有一个内置的负载均衡器,可以进行基本的round-robin负载均衡。在Netflix中,Eureka被用于红/黑部署,Cassandra和memcached部署,以及携带有关服务的应用程序特定的元数据。 68 | 69 |   Eureka集群中的参与节点异步地在彼此之间复制其服务注册表。 与ZK,etcd或Consul相比,Eureka倾向于服务可用性的强一致性; 它留给客户来处理陈旧的读,但在网络分区的情况下具有更强的适应性。 而且,你知道,[网络是可靠的](https://queue.acm.org/detail.cfm?id=2655736)。 --------------------------------------------------------------------------------