├── .DS_Store ├── .gitattributes ├── .gitignore ├── CODE_OF_CONDUCT.md ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Makefile ├── README.md ├── _articles ├── automatic-retries.md ├── backpressure.md ├── circuit-breaking.md ├── front-proxy.md ├── getting-help.md ├── glossary.md ├── health-check.md ├── incremental-deploys.md ├── on-your-laptop.md ├── routing-basics.md ├── routing-configuration.md ├── service-discovery.md ├── service-mesh.md └── ssl.md ├── _config.yml ├── _data ├── building-on.yaml ├── deployment-models.yaml ├── dynamic-configuration.yaml ├── getting-started.yaml ├── observability.yaml └── resilience.yaml ├── _includes ├── article-hero.html ├── article-link.html ├── building-on.html ├── deployment-models.html ├── dynamic-configuration.html ├── footer.html ├── getting-started.html ├── head.html ├── hero.html ├── mailchimp.html ├── nav.html ├── observability.html └── resilience.html ├── _layouts ├── article.html ├── compress.html ├── default.html └── main.html ├── _sass ├── _mixins.scss ├── _variables.scss ├── agency.scss ├── learnenvoy.scss ├── mailchimp.scss └── site.scss ├── assets ├── .DS_Store ├── android-chrome-192x192.png ├── apple-touch-icon.png ├── bootstrap.css ├── bootstrap.min.js ├── browserconfig.xml ├── codeButton.js ├── copy_icon.svg ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── img │ ├── envoy-article-header-bg.jpg │ ├── envoy-header-bg.jpg │ ├── envoy-horizontal-color.png │ └── logo-horiz-3c.svg ├── jquery.min.js ├── main.scss ├── mstile-150x150.png ├── safari-pinned-tab.svg ├── site.webmanifest └── vendor.js ├── circle.yml └── index.html /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/envoyproxy/learnenvoy/4fae9430a36700a2032ade87599576531194ee0a/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.png filter=lfs diff=lfs merge=lfs -text 2 | *.jpg filter=lfs diff=lfs merge=lfs -text 3 | *.gif filter=lfs diff=lfs merge=lfs -text 4 | *.pdf filter=lfs diff=lfs merge=lfs -text 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .sass-cache 2 | node_modules 3 | vendor 4 | .bundle 5 | _site 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at . All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | ruby "~> 2.5.0" 3 | 4 | # Hello! This is where you manage which Jekyll version is used to run. 5 | # When you want to use a different version, change it below, save the 6 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: 7 | # 8 | # bundle exec jekyll serve 9 | # 10 | # This will help ensure the proper Jekyll version is running. 11 | # Happy Jekylling! 12 | gem "jekyll", "3.4.0" 13 | 14 | gem "agency-jekyll-theme" 15 | 16 | # using redcarpet instead of kramdown because it supports comments in markdown 17 | gem "redcarpet", "~> 3.4.0" 18 | 19 | # HTMLProofer is a set of tests to validate your HTML output 20 | gem "html-proofer" 21 | 22 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and 23 | # uncomment the line below. To upgrade, run `bundle update github-pages`. 24 | # gem "github-pages", group: :jekyll_plugins 25 | 26 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 27 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] 28 | 29 | # adds ability to liquefy raw text 30 | group :jekyll_plugins do 31 | gem "liquefy", "~> 0.1.2" 32 | end 33 | 34 | # https://github.com/jekyll/jekyll-sitemap 35 | gem 'jekyll-sitemap' 36 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (5.1.4) 5 | concurrent-ruby (~> 1.0, >= 1.0.2) 6 | i18n (~> 0.7) 7 | minitest (~> 5.1) 8 | tzinfo (~> 1.1) 9 | addressable (2.5.2) 10 | public_suffix (>= 2.0.2, < 4.0) 11 | agency-jekyll-theme (1.0.0) 12 | colorator (1.1.0) 13 | colorize (0.8.1) 14 | concurrent-ruby (1.0.5) 15 | ethon (0.11.0) 16 | ffi (>= 1.3.0) 17 | ffi (1.9.21) 18 | forwardable-extended (2.6.0) 19 | html-proofer (3.8.0) 20 | activesupport (>= 4.2, < 6.0) 21 | addressable (~> 2.3) 22 | colorize (~> 0.8) 23 | mercenary (~> 0.3.2) 24 | nokogiri (~> 1.8.1) 25 | parallel (~> 1.3) 26 | typhoeus (~> 1.3) 27 | yell (~> 2.0) 28 | i18n (0.9.4) 29 | concurrent-ruby (~> 1.0) 30 | jekyll (3.4.0) 31 | addressable (~> 2.4) 32 | colorator (~> 1.0) 33 | jekyll-sass-converter (~> 1.0) 34 | jekyll-watch (~> 1.1) 35 | kramdown (~> 1.3) 36 | liquid (~> 3.0) 37 | mercenary (~> 0.3.3) 38 | pathutil (~> 0.9) 39 | rouge (~> 1.7) 40 | safe_yaml (~> 1.0) 41 | jekyll-sass-converter (1.5.2) 42 | sass (~> 3.4) 43 | jekyll-sitemap (1.2.0) 44 | jekyll (~> 3.3) 45 | jekyll-watch (1.5.1) 46 | listen (~> 3.0) 47 | kramdown (1.16.2) 48 | liquefy (0.1.2) 49 | liquid (3.0.6) 50 | listen (3.1.5) 51 | rb-fsevent (~> 0.9, >= 0.9.4) 52 | rb-inotify (~> 0.9, >= 0.9.7) 53 | ruby_dep (~> 1.2) 54 | mercenary (0.3.6) 55 | mini_portile2 (2.3.0) 56 | minitest (5.11.3) 57 | nokogiri (1.8.2) 58 | mini_portile2 (~> 2.3.0) 59 | parallel (1.12.1) 60 | pathutil (0.16.1) 61 | forwardable-extended (~> 2.6) 62 | public_suffix (3.0.1) 63 | rb-fsevent (0.10.2) 64 | rb-inotify (0.9.10) 65 | ffi (>= 0.5.0, < 2) 66 | redcarpet (3.4.0) 67 | rouge (1.11.1) 68 | ruby_dep (1.5.0) 69 | safe_yaml (1.0.4) 70 | sass (3.5.5) 71 | sass-listen (~> 4.0.0) 72 | sass-listen (4.0.0) 73 | rb-fsevent (~> 0.9, >= 0.9.4) 74 | rb-inotify (~> 0.9, >= 0.9.7) 75 | thread_safe (0.3.6) 76 | typhoeus (1.3.0) 77 | ethon (>= 0.9.0) 78 | tzinfo (1.2.5) 79 | thread_safe (~> 0.1) 80 | yell (2.0.7) 81 | 82 | PLATFORMS 83 | ruby 84 | 85 | DEPENDENCIES 86 | agency-jekyll-theme 87 | html-proofer 88 | jekyll (= 3.4.0) 89 | jekyll-sitemap 90 | liquefy (~> 0.1.2) 91 | redcarpet (~> 3.4.0) 92 | tzinfo-data 93 | 94 | RUBY VERSION 95 | ruby 2.5.0p0 96 | 97 | BUNDLED WITH 98 | 1.16.1 99 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Turbine Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | SHELL := /bin/bash 16 | BUNDLE := bundle 17 | VENDOR_DIR := . 18 | JEKYLL := $(BUNDLE) exec jekyll 19 | 20 | PROJECT_DEPS := Gemfile 21 | 22 | .PHONY: \ 23 | all \ 24 | build \ 25 | check \ 26 | clean \ 27 | include-vendor-deps \ 28 | install \ 29 | update \ 30 | serve \ 31 | test 32 | 33 | all : serve 34 | 35 | check: 36 | $(JEKYLL) doctor 37 | $(HTMLPROOF) --check-html \ 38 | --http-status-ignore 999 \ 39 | --internal-domains localhost:4000 \ 40 | --assume-extension \ 41 | _site 42 | 43 | install: $(PROJECT_DEPS) 44 | $(BUNDLE) install --path vendor/bundler 45 | 46 | update: $(PROJECT_DEPS) 47 | $(BUNDLE) update 48 | 49 | include-vendor-deps: 50 | cp -r $(shell bundle show agency-jekyll-theme)/vendor $(VENDOR_DIR) 51 | 52 | build: install include-vendor-deps 53 | $(JEKYLL) build 54 | 55 | serve: install include-vendor-deps 56 | JEKYLL_ENV=production $(JEKYLL) serve 57 | 58 | test: build 59 | $(BUNDLE) exec htmlproofer ./_site --check-html --disable-external 60 | 61 | clean: 62 | $(JEKYLL) clean 63 | $(BUNDLE) clean 64 | rm -rf vendor 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 2 | [//]: # ( you may not use this file except in compliance with the License. ) 3 | [//]: # ( You may obtain a copy of the License at ) 4 | [//]: # ( ) 5 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 6 | [//]: # ( ) 7 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 8 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 9 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 10 | [//]: # ( implied. See the License for the specific language governing ) 11 | [//]: # ( permissions and limitations under the License. ) 12 | 13 | [//]: # (LearnEnvoy) 14 | 15 | # LearnEnvoy 16 | 17 | [LearnEnvoy](https://learnenvoy.io) is a community content site that helps 18 | organizations get the most out of the 19 | [Envoy proxy](https://envoyproxy.github.io). 20 | 21 | The goal of LearnEnvoy is to help developers go from "hey, Envoy sounds 22 | powerful" to a fully-functional production deployment. 23 | 24 | The content is based on real production deployments, successes and failures, and 25 | interviews with teams running Envoy at scale. The guides cover everything from 26 | the configuration basics to strategies for distributed system resilience. 27 | 28 | ## Project Background 29 | 30 | LearnEnvoy was originally developed at [Turbine 31 | Labs](https://www.turbinelabs.io). It was started based on the experiences 32 | building [Houston](https://www.turbinelabs.io/product), a control plane, 33 | management UI, and observability platform for Envoy. 34 | 35 | We open-sourced this site because we know we're not always right, and even if we 36 | are, Envoy and its best practices are evolving faster than any single 37 | organization can keep up. Feel free to fork it, edit it, share it with others, 38 | and contribute back to it. 39 | 40 | ## Contributing 41 | 42 | Want to contribute a change? Great! Here are a few ways you can jump in: 43 | 44 | - Be sure to read our [Code of Conduct](CODE_OF_CONDUCT.md) 45 | - Browse our [open issues](https://github.com/turbinelabs/learnenvoy/issues) 46 | - Suggest a new section or area for improvement by 47 | [opening an issue](https://github.com/turbinelabs/learnenvoy/issues/new) 48 | 49 | If you're running Envoy at your company and want your success story told, send 50 | an email to hello@turbinelabs.io. We'd love to interview you and post your 51 | experience on the site. 52 | 53 | ## Running LearnEnvoy.io 54 | 55 | ### Prerequisites 56 | 57 | #### Git-lfs 58 | 59 | Before cloning the repo, you'll need to [install git-lfs](https://git-lfs.github.com/). 60 | Otherwise you won't be able to see any of the images. 61 | 62 | #### Ruby 63 | 64 | Jekyll is built with ruby. There are many ways to install ruby on a 65 | mac. Pick the one that is least infuriating to you. Using homebrew is a 66 | fine answer. You'll also need gems (installed with ruby if you're 67 | using homebrew) and bundler, because how else are you going to gem 68 | up your gems. Then we wrap it all with make because we have to hoist some 69 | javascript out of the gems directory. It's beautiful. 70 | 71 | 72 | ```shell 73 | brew install ruby 74 | gem install bundler 75 | ``` 76 | 77 | then verify you have reasonably modern versions 78 | 79 | ```shell 80 | > ruby -v 81 | ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin16] 82 | > bundle -v 83 | Bundler version 1.14.6 84 | ``` 85 | 86 | Now, from within this project directory run 87 | 88 | ```shell 89 | bundle 90 | ``` 91 | 92 | To make sure your Gems are packaged up correctly for running jekyll 93 | 94 | ### Building the site 95 | 96 | To serve the site for local development, run 97 | 98 | ``` 99 | make serve 100 | ``` 101 | 102 | Then go to http://localhost:4000 103 | 104 | To build the site for distribution run 105 | 106 | ```shell 107 | make build 108 | ``` 109 | 110 | And gzip or whatever all the stuff in `_site`. 111 | 112 | ## Site Architecture 113 | 114 | ### Theme 115 | 116 | We use the [agency theme](https://github.com/y7kim/agency-jekyll-theme) for the 117 | site. Styling overrides are in `assets/main.scss` and in the `_sass` 118 | directory. We have copied all of the scss assets from the gem, so we shouldn't 119 | have to worry about order of application from the gem and our thing (non-gem 120 | files _should_ take precedence) 121 | 122 | ### Topics 123 | 124 | The main page is organized along a series of topics. Topics are defined in four 125 | places (gross). 126 | 127 | 1. `_includes/nav.html` defines the topmost nav. Each section needs an entry 128 | here 129 | 2. `_layouts/main.html` has an include for each topic 130 | 3. `_includes/.html` controls rendering for the topic 131 | 4. `_data/.yaml` provides a structured "database" of entries in a topic 132 | 133 | ### Articles 134 | 135 | If an item in `_data/.yaml` contains an `article` field, jekyll will look 136 | for a corresponding markdown file in the `_articles` subdirectory. Articles are 137 | rendered with the layout in `_layouts/article.html`. see 138 | `_data/getting-started.yaml` for a _very_ slim example for the 'on your laptop' 139 | article. 140 | -------------------------------------------------------------------------------- /_articles/automatic-retries.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Automatic Retries 4 | description: > 5 | Automatic retries are a powerful way to add resilience to your system with 6 | essentially no changes to your services. This article covers configuration 7 | for Envoy's retries, including when to retry, choosing defaults, and how to 8 | configure other Envoy features that augment retries. 9 | --- 10 | 11 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 12 | [//]: # ( you may not use this file except in compliance with the License. ) 13 | [//]: # ( You may obtain a copy of the License at ) 14 | [//]: # ( ) 15 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 16 | [//]: # ( ) 17 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 18 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 19 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 20 | [//]: # ( implied. See the License for the specific language governing ) 21 | [//]: # ( permissions and limitations under the License. ) 22 | 23 | [//]: # (Automatic Retries) 24 | 25 | Automatic retries are a powerful way to add resilience to your system with 26 | essentially no changes to your services. In many systems, failed requests can 27 | be retried without any negative consequences, shielding users from transient 28 | issues. 29 | 30 | Envoy provides a simple configuration option for retrying requests. Consider 31 | specifics of your system as you set up retries across each route: 32 | 33 | - Choose appropriate defaults 34 | - Limit retry-able requests 35 | - Consider the calling context 36 | 37 | ## Choose Appropriate Defaults 38 | 39 | Retries are specified as part of a route definition by adding a retry_policy 40 | field to the route_action. In the API, this would be returned from the Route 41 | Discovery Service (RDS). 42 | 43 | ## A typical Envoy retry policy 44 | 45 | Here's what a simple retry configuration looks like for a single route: 46 | 47 | ```yaml 48 | retry_on: "5xx" 49 | num_retries: 3 50 | per_try_timeout_ms: 2000 51 | ``` 52 | 53 | The `retry_on` parameter specifies **which types of responses to retry** this 54 | request on. 5xx is a good place to start, as it will retry all server errors. 55 | There are more specific subsets that Envoy supports (e.g. gateway-error, 56 | connect-failure, and refused-stream), but all of these are caught with 5xx. 57 | 58 | By default, Envoy will set the **number of retries** to one with 59 | `num_retries`. There’s little downside to increasing this to three, especially 60 | for relatively short requests, as Envoy will limit the total time spent to the 61 | overall request timeout, including the initial request and all retries. 62 | 63 | The `per_try_timeout_ms` field sets a **timeout for each retry** in 64 | milliseconds. Without this parameter, any request that times out will not be 65 | retried, since the default is the same as the calling request’s timeout. While 66 | it’s not a big deal to leave this out, setting it to the 99th percentile of 67 | normal latency allows Envoy to retry requests that are taking a long time due to 68 | a failure. (Note that this limit may be longer than the total request 69 | timeout — more on that below.) 70 | 71 | ## Limit Retry-able Requests 72 | Once you have your defaults in place, there are several types of calls for 73 | which it does not make sense to retry requests. 74 | 75 | First, **do not retry requests where retrying would change the result**, such 76 | as non-idempotent transactions. Most frameworks for monolithic services wrap 77 | all requests in a DB transaction, guaranteeing any failure will roll back all 78 | state changes, allowing the caller to try again. Unfortunately, in the 79 | microservices world, an intermediate service may not be as diligent in 80 | unwinding partial work across several services on a failure. Even worse, the 81 | unwinding may fail, or the caller won’t be informed of the final state. In 82 | general, enabling retries for all read requests is safe and effective, since 83 | most systems tend to be read-heavy. Since routes in Envoy can be specified by 84 | HTTP method, retrying GET requests is a good place to start. 85 | 86 | Similarly, **do not retry expensive requests**, especially if they cannot be 87 | canceled. This is subjective, because these requests can “correctly” be 88 | retried. The problem is that retrying them may run the system out of resources, 89 | creating a set of cascading failures. As a general rule, don’t retry requests 90 | where the user would be impatiently waiting for the result. User logins should 91 | almost always be retried quickly; complex analytics calculations should fail 92 | back to the user and let either the UI or the user retry immediately. 93 | 94 | For complex cases, remember that any of this configuration can be overridden 95 | with HTTP headers. It’s better to configure routes to be conservative with 96 | their retries and allow specific calling code to request more aggressive retry 97 | behavior. 98 | 99 | ## Consider the Calling Context 100 | 101 | For internal service calls, it’s important to consider the restrictions imposed 102 | on the caller as well. 103 | 104 | Since Envoy will limit the total duration of retries, consider the relationship 105 | between the route's global timeout 106 | ([`timeout_ms`](https://www.envoyproxy.io/docs/envoy/latest/api-v1/route_config/route.html#config-http-conn-man-route-table-route-timeout)), 107 | the upstream routes' timeout (also 108 | ([`timeout_ms`](https://www.envoyproxy.io/docs/envoy/latest/api-v1/route_config/route.html#config-http-conn-man-route-table-route-timeout)), 109 | the per-retry timeout 110 | ([`per_try_timeout_ms`](https://www.envoyproxy.io/docs/envoy/latest/api-v1/route_config/route.html#config-http-conn-man-route-table-route-retry)), 111 | and the number of retries 112 | ([`num_retries`](https://www.envoyproxy.io/docs/envoy/latest/api-v1/route_config/route.html#config-http-conn-man-route-table-route-retry)). 113 | In general, it's better to fail quickly and retry than to let long requests 114 | attempt to finish. This will, perhaps counterintuitively, increase success rates 115 | and decrease most latency. 116 | 117 | As an example, consider a request with a 500ms timeout that makes a single 118 | upstream call with a maximum of 3 retries, limited to 250ms each. The problem 119 | here is the # of retries times the individual retry limit is significantly 120 | higher than the global timeout, so Envoy can’t make more than 2 calls before the 121 | global timeout fails the request. This isn’t fundamentally bad, but the 250ms 122 | timeout doesn't allow a full retry on timeout. (Sometimes failures are quick, 123 | so Envoy will be able to complete the second request, and having a lot of 124 | retries will help.) As a starting point, lowering the upstream timeout to 100ms 125 | will allow several retries, accounting for the jitter that Envoy adds between 126 | calls. 127 | 128 | On the other hand, if the request makes many parallel requests (“high fan-out”) 129 | without an aggresive global timeout, adding retries will result in consistently 130 | poor performance. Imagine a service (with no global timeout) that makes 100 131 | requests with an average of 150ms latency and a 500ms timeout on each upstream 132 | called. Without retries, the request will be bounded at ~500ms -- either the 133 | request will fail when some of the upstream calls fail, or it will 134 | succeed. Adding 3 retries will cause this service to shoot from 500ms to 135 | 2,000ms on failure — a huge slowdown, which is only compounded in a service mesh 136 | with deep calls stacks. This kind of added latency may cause more failures than 137 | they fix! To avoid this, make sure to add a caller timeout to any service that 138 | has high-fanout before adding retries to its upstream calls. 139 | 140 | ## Next Steps 141 | 142 | Finally, it is strongly recommended that you set up Global Circuit Breaking in 143 | conjunction with automatic retries. Retrying error requests 3x can triple the 144 | volume of error traffic, making Envoy an amplifier for a misconfigured calling 145 | service. Global circuit breaking helps selectively shed load when this sort of 146 | failure occurs, preventing it from cascading to multiple services. 147 | 148 | For more detail, and advanced configuration information, read about them in the 149 | [Envoy docs](https://www.envoyproxy.io/docs/envoy/latest/api-v1/route_config/route.html#config-http-conn-man-route-table-route-retry). 150 | -------------------------------------------------------------------------------- /_articles/backpressure.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Backpressure 4 | description: > 5 | How Envoy handles overloaded microservices in a service mesh architecture. A 6 | service mesh based on Envoy Proxy frees up clients from implementing rate 7 | limiting, retries, or timeouts. This articles shows how clients must deal with 8 | failures and backpressure from Envoy. 9 | --- 10 | 11 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 12 | [//]: # ( you may not use this file except in compliance with the License. ) 13 | [//]: # ( You may obtain a copy of the License at ) 14 | [//]: # ( ) 15 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 16 | [//]: # ( ) 17 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 18 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 19 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 20 | [//]: # ( implied. See the License for the specific language governing ) 21 | [//]: # ( permissions and limitations under the License. ) 22 | 23 | [//]: # (Front Proxy) 24 | 25 | ## A Guide to Envoy’s Backpressure 26 | 27 | One of the biggest advantages of a service mesh is that it frees up clients from 28 | implementing features like rate limiting, retries, or timeouts. It’s easy to 29 | think that with a service proxy like Envoy handling these features, there’s no 30 | further work to be done. While this is almost true, if there’s a real failure, 31 | (e.g. multiple retries that never succeed), the client will ultimately have to 32 | handle it. 33 | 34 | Whether you handle this with custom code in each service or with a set of thin 35 | client libraries is up to you, but here are the behaviors you can expect to see 36 | from Envoy when things go wrong with HTTP/1, HTTP/2, or gRPC requests. 37 | 38 | Two quick definitions, used by Envoy: 39 | 40 | - Upstream connections are the service Envoy is initiating the connection to. 41 | - Downstream connections are the client that is initiating a request through 42 | Envoy. 43 | 44 | These terms take their origin from traditional computer networking; information 45 | flows like water through Envoy from 46 | [upstream](https://en.wikipedia.org/wiki/Upstream_(networking)) (the service 47 | that eventually responds to the request) to 48 | [downstream](https://en.wikipedia.org/wiki/Downstream_(networking)) (the caller 49 | making the request). In a service mesh, all services are often co-located in the 50 | same cloud, but there's still utility in thinking in terms of traffic flow. 51 | 52 | ## Envoy Failure Modes 53 | 54 | The following is a comprehensive list of ways Envoy can send an unsuccessful 55 | response to the downstream client. 56 | 57 | ### Rate Limiting Failure 58 | 59 | **What it is:** The [Rate 60 | Limiting](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/global_rate_limiting) 61 | service determined that this request exceeds the quotas it sets and should be 62 | tried again later. 63 | 64 | **Result:** The client receives an [HTTP 429](https://httpstatuses.com/429) 65 | response. 66 | 67 | ### Timeout Failure 68 | 69 | **What it is:** The upstream connection took longer to respond than the timeout 70 | set on the route. 71 | 72 | **Result:** The client receives an [HTTP 504](https://httpstatuses.com/504) 73 | (Read More) 74 | 75 | ### Empty Cluster 76 | 77 | **What it is:** There are no hosts available in a cluster. Note that this is NOT 78 | what happens when all hosts fail either health checks or outlier detection. In 79 | either of those situations, Envoy will notice the number of hosts is below the 80 | panic threshold and balance across all known hosts. 81 | 82 | **Result:** Returns an [HTTP 503](https://httpstatuses.com/503) with the body 83 | text “no healthy upstream”. 84 | 85 | ### Unresponsive Upstream 86 | 87 | **What it is:** The upstream host is unresponsive. 88 | 89 | **Result:** Returns an [HTTP 503](https://httpstatuses.com/503) with the body 90 | text “upstream connect error or disconnect/reset before headers”. 91 | 92 | ### Circuit Breaker Failed Open 93 | 94 | **What it is:** Due to too many unsuccessful or outstanding requests to this 95 | upstream, Envoy has tripped the circuit breaker and is failing the request. 96 | 97 | **Result:** The client receives an [HTTP 503](https://httpstatuses.com/503) with 98 | the `x-envoy-overloaded: true` header set. (Read More) 99 | 100 | ### Maintenance mode 101 | 102 | **What it is:** Routes to this cluster have been configured with 103 | `upstream.maintenance_mode.`, and this request is in the fraction 104 | of requests that is unsuccessful 105 | 106 | **Result:** Returns an [HTTP 503](https://httpstatuses.com/503) with the 107 | `x-envoy-overloaded: true` header set. (Read More) 108 | 109 | ### Domain or Route not found 110 | 111 | **What it is:** Envoy is not configured to serve this URL. 112 | 113 | **Result:** The client receives an [HTTP 404](https://httpstatuses.com/404). 114 | 115 | Note: Envoy only supports HTTP/1.1 and newer, which requires the presence of a 116 | `Host` header. In particular, this means that requests to `127.0.0.1` or the IP 117 | that Envoy is listening on will almost always return a 404, even if Envoy is 118 | correctly configured to serve one or more domains. 119 | 120 | ### Upstream Connection Closed 121 | 122 | **What it is:** When the upstream closes the connection before the response is 123 | finished sending, Envoy cannot send a complete response to the downstream. 124 | 125 | **Result:** This depends on whether the downstream has started receiving data. 126 | 127 | - If it has not (i.e. the upstream disconnects quickly), the downstream 128 | connection is reset. 129 | - If it has, the downstream receives an [HTTP 130 | 503](https://httpstatuses.com/503) and the body text “upstream connect error 131 | or disconnect/reset before headers” 132 | 133 | ### Envoy is Overloaded 134 | 135 | **What it is:** When Envoy itself is overloaded, it will stall. Envoy stops 136 | reading from the downstream client when it wants to exert back pressure (e.g., 137 | local kernel buffer fills, then remote kernel buffer, then client blocks). 138 | 139 | **Result:** Downstream connections are blocked with no error. 140 | 141 | ## What Clients Should Handle 142 | 143 | In addition to the errors above, clients should also handle scenarios that 144 | out-of-process proxies cannot deal with. These include: 145 | 146 | - Thread-local circuit breakers 147 | - Timeouts if Envoy is blocking 148 | - A code path that returns a sensible result when a failure has occurred 149 | 150 | ## Next Steps 151 | 152 | Once your client libraries can handle it, go implement some of Envoy's 153 | resilience features, such as: 154 | 155 | - [Automatic retries](automatic-retries.html) 156 | - [Circuit breaking](circuit-breaking.html) 157 | - [Health checks](health-check.html) 158 | -------------------------------------------------------------------------------- /_articles/circuit-breaking.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Circuit Breaking 4 | description: > 5 | Envoy's circuit breaking lets you configure failure thresholds to prevent 6 | cascading failure in a microservices architecture. Learn how to configure 7 | circuit breakers on clusters and best practices for tuning the thresholds. 8 | --- 9 | 10 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 11 | [//]: # ( you may not use this file except in compliance with the License. ) 12 | [//]: # ( You may obtain a copy of the License at ) 13 | [//]: # ( ) 14 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 15 | [//]: # ( ) 16 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 17 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 18 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 19 | [//]: # ( implied. See the License for the specific language governing ) 20 | [//]: # ( permissions and limitations under the License. ) 21 | 22 | [//]: # (Circuit Breaking) 23 | 24 | In the world of microservices, services often make calls to other services. But 25 | what happens when a service is busy, or unable to respond to that call? How do 26 | you avoid a failure in one part of your infrastructure cascading into other 27 | parts of your infrastructure? One approach is to use circuit breaking. 28 | 29 | Circuit breaking lets you configure failure thresholds that ensure safe 30 | maximums after which these requests stop. This allows for a more graceful 31 | failure, and time to respond to potential issues before they become larger. 32 | It’s possible to implement circuit breaking in a few parts of your 33 | infrastructure, but implementing these circuit breakers within services means 34 | they are vulnerable to the same overload and failure we’re hoping to prevent. 35 | Instead, we can configure circuit breaking at the network layer within Envoy, 36 | and combine it with other traffic shaping patterns to ensure healthy and stable 37 | infrastructure. 38 | 39 | ## Configuring circuit breaking 40 | 41 | Envoy provides simple configuration for circuit breaking. Consider the 42 | specifics of your system as you set up circuit breaking. 43 | 44 | Circuit breaking is specified as part of a Cluster (a group of similar upstream 45 | hosts) definition by adding a `circuit_breakers` field. Clusters are returned 46 | from the Cluster Discovery Service (CDS), either in the bootstrap config, or a 47 | remote CDS server . 48 | 49 | ## Circuit Breaker Configuration 50 | 51 | Here's what a simple circuit breaking configuration looks like: 52 | 53 | ```yaml 54 | circuit_breakers: 55 | thresholds: 56 | - priority: DEFAULT 57 | max_connections: 1000 58 | max_requests: 1000 59 | - priority: HIGH 60 | max_connections: 2000 61 | max_requests: 2000 62 | ``` 63 | 64 | In this example, there are a few fields that allow for a lot of service 65 | flexibility: 66 | 67 | `thresholds` allows us to define priorities and limits for the type of traffic 68 | that our service responds to. 69 | 70 | `priority` refers to how routes defined as `DEFAULT` or `HIGH` are treated by 71 | the circuit breaker. Using the settings above, we would want to set any 72 | requests that shouldn’t wait in a long queue to HIGH. For example: POST 73 | requests in a service where a user wants to make a purchase, or save their 74 | state. 75 | 76 | `max_connections` are the maximum number of connections that Envoy will make to 77 | our service clusters. The default for these is 1024, but in real-world 78 | instances we may drastically lower them. 79 | 80 | `max_requests` are the maximum number of parallel requests that Envoy makes to 81 | our service clusters. The default is also 1024. 82 | 83 | ## Typical Circuit Breaker Policy 84 | 85 | Essentially all clusters will benefit from a simple circuit breaker at the 86 | network level. Because HTTP/1.1 and HTTP/2 have different connection behaviors 87 | (one connection per request vs. many requests per connection), clusters with 88 | different protocols will each use a different option: 89 | 90 | - For **HTTP/1.1** connections, use `max_connections`. 91 | - For **HTTP/2** connections, use `max_requests`. 92 | 93 | Circuit breakers prevent catastrophic outages based on timeout failures, where a 94 | single service cascades everywhere. The most insidious failures happen not 95 | because a service is down, but because it’s hanging on to requests for tens of 96 | seconds. Generally, it’s better for one service to be completely down than for 97 | all services to be outside their SLO because they’re waiting for a timeout deep 98 | in the stack. 99 | 100 | A good value for either of these options depends on two things: the number of 101 | connections/requests to your service and the typical request latency. For 102 | example, an HTTP/1 service with 1,000 requests / second and average latency of 2 103 | seconds will typically have 2,000 connections open at any given time. Because 104 | circuit breakers trip when there are a large number of slower-than-normal 105 | connections, consider a starting point for this service in the range of 10 x 106 | 2,000. This would open the breaker when most of the requests in the last 10 107 | seconds have failed to return any response. Exactly what you pick will depend on 108 | the spikiness of your load and how overprovisioned the service is. 109 | 110 | ## Advanced circuit breaking 111 | 112 | Now that you’ve seen a basic configuration and policy for circuit breaking, 113 | we’ll discuss more advanced circuit breaking practices. These advanced 114 | practices will add more resiliency to your infrastructure at the network level. 115 | 116 | ### Break–on–latency 117 | 118 | As mentioned above, one of the most common use cases of circuit breakers is to 119 | prevent failures that are caused when a service is excessively slow, but not 120 | fully down. While Envoy doesn’t directly provide an option to trip the breaker 121 | on latency, you can combine it with 122 | [Automatic Retries](automatic-retries.html) 123 | to emulate this behavior. 124 | 125 | To break on an unexpected spike in slow requests, reduce the latency threshold 126 | for retries and enable circuit break on lots of retries using the `max_retries` 127 | option. 128 | 129 | If you do this, monitor the results closely! Many practitioners report that 130 | setting too low a latency threshold is the only time they’ve *created* an 131 | outage by adding circuit breakers. When this latency threshold too low, you can 132 | DoS your services. Start higher than you think you need, and lower it over 133 | time. 134 | 135 | ### Configure breaking based on a long queue of retries 136 | 137 | Even if you’re only [retrying requests](automatic-retries.html) 138 | on connection errors, it is valuable to set up circuit breaking. Because 139 | retries have the potential to increase the number of requests by 2x or more, 140 | circuit breaking using the `max_retries` parameter protects services from 141 | being overloaded by too many active retries. Set this value to a similar 142 | number as `max_connections` or `max_requests`—a fraction of the total number of 143 | requests the service typically handles in a 10-second window. If the service 144 | has as many retries outstanding as the typical number of requests, it’s broken 145 | and should be disabled. 146 | 147 | ## Next Steps 148 | 149 | With circuit breaking configured, your service is equipped to help selectively 150 | shed load when failure occurs, preventing it from cascading to multiple 151 | services. Combining this tool with 152 | [automatic retries](automatic-retries.html) 153 | makes for robust services that are able to handle common issues at the network 154 | level. 155 | -------------------------------------------------------------------------------- /_articles/front-proxy.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Front Proxy 4 | description: > 5 | One of the most powerful ways to deploy Envoy is as a front proxy. This 6 | article covers setting up an Envoy-based load balancer in Kubernetes, EC2, 7 | GCP, and more, including practical guides on SSL, multiple data centers, and 8 | monitoring. 9 | --- 10 | 11 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 12 | [//]: # ( you may not use this file except in compliance with the License. ) 13 | [//]: # ( You may obtain a copy of the License at ) 14 | [//]: # ( ) 15 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 16 | [//]: # ( ) 17 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 18 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 19 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 20 | [//]: # ( implied. See the License for the specific language governing ) 21 | [//]: # ( permissions and limitations under the License. ) 22 | 23 | [//]: # (Front Proxy) 24 | 25 | ## Front Proxy Deployment 26 | 27 | One of the most powerful ways to deploy Envoy is as a front proxy. In this 28 | configuration, Envoy acts as the primary load balancer for customer requests 29 | from the public internet. Managing this public traffic—also called north-south 30 | traffic—is something that every web app must do, so it’s a natural place to 31 | start with Envoy. This kind of deployment style is also called an edge proxy or 32 | simply a load balancer. 33 | 34 | Starting with a front proxy is straightforward, because the first step is 35 | simply to port whatever existing configuration you have to Envoy. When you 36 | deploy your Envoy-based front proxy, you can set it up in parallel to your 37 | current setup, giving you the change to test and evaluate Envoy before sending 38 | production traffic through it. Once Envoy is stable and tested, it provides a 39 | high-leverage place to start enabling Envoy’s more advanced features around 40 | resilience and observability for your whole organization. 41 | 42 | ## Deploying a Front Proxy 43 | 44 | Though Envoy is capable enough to be deployed right at the edge of your 45 | network, most public cloud providers expose layer 3/4 load balancers with more 46 | capabilities than you need. The typical deployment will use 47 | [AWS’ NLB](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html), 48 | [GCP’s Regional NLB](https://cloud.google.com/compute/docs/load-balancing/network/), 49 | or a minimal configuration of a more feature-rich load balancer 50 | like AWS ALB. These baked-in load balancers can handle regional or global 51 | traffic balancing, which is impossible for a set of VMs running Envoy (which 52 | are necessarily constrained to a single availability zone) to handle. 53 | 54 | A simple, robust deployment of an Envoy front proxy uses an autoscaling group 55 | of Envoys based on network traffic. Based on where your routing rules currently 56 | live (NGINX config files, AWS ALB configuration, etc.), you will need to port 57 | these to a set of Envoy routes. See 58 | [Routing Configuration](routing-configuration.html) for more details. 59 | 60 | Most modern apps will want to implement a dynamic control plane, since the 61 | instances within each service are dynamic. A static configuration can only 62 | point to a fixed set of instances, while a dynamic control plane can keep Envoy 63 | up-to-date on the state of your environment, typically by reading from your 64 | service discovery registry. See 65 | [Integrating Service Discovery with Envoy](service-discovery.html) 66 | for implementations that will do this for you, like 67 | [Rotor](https://github.com/turbinelabs/rotor). 68 | 69 | For an example of how this would work in AWS, 70 | [see this repository, which uses AWS, CloudFormation, and Rotor](https://github.com/turbinelabs/examples/tree/master/rotor-nlb). 71 | 72 | If you’re looking to deploy Envoy for internal traffic only, see 73 | [Basic Service Mesh](service-mesh.html). 74 | 75 | ## Deploying Envoy in Kubernetes 76 | 77 | If you’re in Kubernetes, you can point NLBs directly to a an exposed Kubernetes 78 | service in front of an Envoy deployment. 79 | 80 | Here’s what that Deployment might look like. It uses 81 | [envoy-simple](https://github.com/turbinelabs/envoy-simple), a Docker 82 | container that allows Envoy to be fully dynamically configured by specifying a 83 | control plane implementation via environment variables. Simply change 84 | `ENVOY_XDS_HOST` to the network location of your control plane (typically 85 | another Kubernetes service). 86 | 87 | ```yaml 88 | apiVersion: extensions/v1beta1 89 | kind: Deployment 90 | metadata: 91 | name: envoy-front-proxy 92 | spec: 93 | replicas: 2 94 | template: 95 | spec: 96 | containers: 97 | - image: turbinelabs/envoy-simple:0.17.2 98 | imagePullPolicy: Always 99 | name: envoy-simple 100 | ports: 101 | - containerPort: 80 102 | env: 103 | - name: ENVOY_XDS_HOST 104 | value: "control-plane.svc.cluster.local" # Wherever your xDS implementation lives 105 | - name: ENVOY_XDS_PORT 106 | value: "50000" 107 | ``` 108 | 109 | Assuming you’ve saved this file as `envoy.yaml`, you can create a load balancer 110 | in your cloud provider with `kubectl`. 111 | 112 | ```shell 113 | $ kubectl create -f envoy.yaml 114 | $ kubectl expose deployment --type=LoadBalancer --port=80 envoy-front-proxy 115 | ``` 116 | 117 | You can also use an ingress controller like 118 | [Contour](https://github.com/heptio/contour) if you want to manage everything 119 | through Kubernetes. These expose Envoy’s configuration as 120 | [Kubernetes Ingress Resources](https://kubernetes.io/docs/concepts/services-networking/ingress/). 121 | This is simple, but less expressive than configuring Envoy through a 122 | general-purpose control plane, as the Kubernetes ingress controller spec is 123 | lowest-common-denominator by design, with support for only a subset of Envoy’s 124 | capabilities. There are also Kubernetes-native API Gateways like 125 | [Ambassador](https://github.com/datawire/ambassador) that offer expanded 126 | functionality by using other, more expressive Kubernetes resources for 127 | configuration. 128 | 129 | Note that while running Envoy in Kubernetes is simpler if you’re committed to 130 | Kubernetes, many people start by running Envoy outside of Kubernetes in order 131 | to manage the migration. Running Envoy outside of Kubernetes ensures that any 132 | cluster failures doesn’t take down your Envoy front proxy. If you leave Envoy 133 | running outside the cluster after completing you migration, it also gives you 134 | flexibility to keep running other orchestrators, or even migrate to the thing 135 | that replaces Kubernetes! 136 | 137 | ## SSL and Metrics 138 | 139 | Front proxies are a natural place to terminate SSL, to ensure that individual 140 | services don’t have to. You can either do in your cloud’s load balancer (e.g. 141 | AWS ELB) or in Envoy itself. To configure SSL, see [this article](ssl.html). 142 | 143 | As a common choke point for all traffic, front proxies are a great place to 144 | generate high-level metrics for your site. Make sure to at least send request 145 | health metrics to your dashboards: latency, volume, and success rate. Coarsely, 146 | this gives you a simple dashboard for “is the site up?” and partitioning the 147 | traffic by upstream cluster can give you health metrics for each service that 148 | are more relevant to the service teams. 149 | 150 | If you generate logs from your current front proxy, Envoy can be configured to 151 | send request-level access logs to a centralized server. Be aware that the 152 | volume of traffic at the edge can make logging expensive or slow, so this may 153 | not be cost-effective if it’s not a critical capability. 154 | 155 | Similarly, Envoy provides drop-in configuration for tracing, and and the front 156 | proxy is a great place to generate those tracing headers. 157 | 158 | ## Multiple Data Centers Made Simple 159 | 160 | There are two strategies for running services in multiple zones (availability 161 | zones, regions, data centers, etc.). You can pick a single strategy, or you can 162 | run both hierarchically. 163 | 164 | If you have a _single network space_, your best bet is to use 165 | **Envoy’s Zone Aware Routing** to handle any underlying discrepancies in the 166 | topology seamlessly. This strategy is best used with closely connected zones 167 | like AWS Availability Zones, where multiple zones are operationally a single 168 | unit, but cross-zone traffic incurs a cost. In this setup, your network load 169 | balancer would balance across a front proxy that spans multiple zones, and 170 | Envoy would keep each request in the zone it was first load balanced to. This 171 | will minimize cross-zone traffic (which is expensive and slow), while 172 | maintaining the ability to incrementally fall back to out-of-zone instances if 173 | the local ones are failing. 174 | 175 | Setting up zone-aware load balancing requires two options to be set: 176 | 177 | - Each cluster (statically defined or returned by the control plane via CDS) 178 | must enable zone-aware routing. 179 | - Each Envoy must set `local_cluster_name` to one of the named clusters. 180 | 181 | Statically defined, this looks like: 182 | 183 | ```yaml 184 | local_cluster_name: service1 185 | clusters: 186 | - name: service1 187 | zone_aware_lb_config: 188 | min_cluster_size: 3 189 | ``` 190 | 191 | On the other hand, _fully isolated zones_ should be configured with 192 | **entirely separate service discovery integrations**. Instead of giving each 193 | Envoy the full routing table with all instances, it’s better to only enable 194 | each Envoy to route to instances in its own zone. To enable these zones to fail 195 | over gracefully, you can add remote front proxies to each cluster with a low 196 | weight. 197 | 198 | This “backhaul” path will allow automatic failover while allowing zones to 199 | maintain different internal configurations. For example, if you are doing a 200 | release in the EU region, having the US region fail to the EU’s front proxy 201 | keeps the US region from inadvertently routing too much traffic to the new 202 | version if there’s a failure mid-release. 203 | 204 | ## Best Practices 205 | 206 | Once you have a front proxy up and running, there are several ways to make 207 | operating it easier for you, your team, and the rest of the company. 208 | 209 | ### Make routing self-serve. 210 | 211 | Microservices mean a lot more changes, and service 212 | teams should be part of the process. Add guardrails (either people process or 213 | RBAC-style rules) to prevent things from breaking. 214 | 215 | ### Centralize authentication at the edge. 216 | 217 | Adding a single authentication call at the edge prevents every service from 218 | re-verifying the user each time. Take the cookie from the user, verify it with 219 | the authentication service, and store the result (including any commonly used 220 | data like a user ID) in a header that gets passed to internal services and 221 | trusted without further verification. 222 | 223 | ### Add protections from bad actors and unexpected traffic spikes. 224 | 225 | This means [retries](automatic-retries.html), 226 | [health checks](health-check.html), etc. What this looks like depends strongly 227 | on your infrastructure and the types of issues you’re looking to mitigate. 228 | 229 | ## Next Steps 230 | 231 | While this article has focused on how to handle traffic coming from outside 232 | your network, it's also possible for Envoy to handle traffic between services 233 | (or "east-west" traffic). For a lightweight way to set up this internal mesh, 234 | you can route internal requests through this front proxy (or a similarly 235 | configured proxy pool specifically for east-west). Beyond that, you can take 236 | better advantage of Envoy’s unique features as a lightweight sidecar by 237 | [setting up a Basic Service Mesh](service-mesh.html). 238 | -------------------------------------------------------------------------------- /_articles/getting-help.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Getting Help 4 | description: > 5 | Trying to debug Envoy and need more information? Learn how to get more 6 | data out of Envoy and the best places to ask for help! 7 | --- 8 | 9 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 10 | [//]: # ( you may not use this file except in compliance with the License. ) 11 | [//]: # ( You may obtain a copy of the License at ) 12 | [//]: # ( ) 13 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 14 | [//]: # ( ) 15 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 16 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 17 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 18 | [//]: # ( implied. See the License for the specific language governing ) 19 | [//]: # ( permissions and limitations under the License. ) 20 | 21 | [//]: # (Getting Help) 22 | 23 | ## How to Get More Information 24 | 25 | To enable debug logging for Envoy, send the following request to 26 | the admin interface, which is included in the bootstrap, or 27 | configured separately in the case of a custom xDS configuration. 28 | 29 | `GET /logging` 30 | 31 | You can also pass these flags to the Envoy binary: 32 | 33 | ```console 34 | -l , --log-level --log-path 35 | ``` 36 | 37 | It will set both the log level, and the path in which your logs 38 | are stored. 39 | 40 | ## How to Get Help 41 | 42 | The Envoy community is active, and lives on Github, as well as 43 | several mailing lists, and a Slack team. Find out more by 44 | visiting 45 | [the contact section](https://github.com/envoyproxy/envoy#contact) 46 | 47 | When talking to other users and maintainers on Slack, be sure to 48 | clearly identify your issues, the steps you've attempted to 49 | remedy each one, and provide any pertinent logs. As a very 50 | developer-friendly environment, help abounds. The other users 51 | you will encounter are at a variety of experience levels with 52 | Envoy, but everyone wants to collaborate to make Envoy better. 53 | Have fun with it. 54 | -------------------------------------------------------------------------------- /_articles/glossary.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Glossary 4 | description: > 5 | A list of common Envoy terms and their meanings. 6 | --- 7 | 8 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 9 | [//]: # ( you may not use this file except in compliance with the License. ) 10 | [//]: # ( You may obtain a copy of the License at ) 11 | [//]: # ( ) 12 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 13 | [//]: # ( ) 14 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 15 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 16 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 17 | [//]: # ( implied. See the License for the specific language governing ) 18 | [//]: # ( permissions and limitations under the License. ) 19 | 20 | [//]: # (Glossary) 21 | 22 | xDS is a suite of configuration service APIs that allow for dynamic 23 | configuration of an Envoy proxy. It's possible to configure Envoy with a few or 24 | all of these services. This overview will describe what each service does, and 25 | why you would use it. 26 | 27 | ## CDS 28 | 29 | The Cluster Discovery Service tells Envoy about your clusters. In Envoy’s 30 | vernacular, a “cluster” is a named group of host/ports, over which it will 31 | load-balance traffic. CDS also allows configuration health checks, and TLS, and 32 | other connection types. Cluster instances can be listed statically in CDS or, 33 | more commonly, dynamically managed using EDS 34 | 35 | Read more about CDS configuration [here](https://www.envoyproxy.io/docs/envoy/latest/configuration/cluster_manager/cds). 36 | 37 | ## EDS 38 | 39 | The Endpoint Discovery Service tells Envoy about the instances (endpoints) of 40 | your clusters. EDS produces a list of instances for each cluster, and some 41 | metadata about each instance. 42 | 43 | Read more about EDS configuration [here](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/eds.proto.html#envoy-api-file-envoy-api-v2-eds-proto). 44 | 45 | ## LDS 46 | 47 | The Listener Discovery Service tells Envoy what ports to listen on, and what 48 | protocols to terminate on those ports. You can also configure TLS and request 49 | logging with this service. 50 | 51 | Read more about LDS configuration [here](https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/lds). 52 | 53 | ## RDS 54 | 55 | The Route Discovery Service tells Envoy about the routes for each HTTP Listener 56 | configured in the LDS. You can partition the URL-space in to multiple paths, 57 | each potentially backed by a different services. You can also add redirects, 58 | request and response headers, timeouts, and retry policies. 59 | 60 | Read more about RDS configuration [here](https://www.envoyproxy.io/docs/envoy/latest/configuration/http_conn_man/rds). 61 | 62 | ## Learn More 63 | 64 | For the full xDS configuration reference, read more [here](https://www.envoyproxy.io/docs/envoy/latest/configuration/configuration.html#config). 65 | -------------------------------------------------------------------------------- /_articles/health-check.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Healthly Hosts in Envoy 4 | description: > 5 | Envoy can be configured with both active and passive health checking in 6 | order to make the best load balancing decision possible. See how to configure 7 | health checking and outlier detection, with example code and best practices 8 | for tuning configuration values. 9 | --- 10 | 11 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 12 | [//]: # ( you may not use this file except in compliance with the License. ) 13 | [//]: # ( You may obtain a copy of the License at ) 14 | [//]: # ( ) 15 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 16 | [//]: # ( ) 17 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 18 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 19 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 20 | [//]: # ( implied. See the License for the specific language governing ) 21 | [//]: # ( permissions and limitations under the License. ) 22 | 23 | [//]: # (Healthy Hosts on Envoy) 24 | 25 | The only thing better than finding and fixing problems quickly is not having 26 | problems at all. While many issues are caused by bugs in code, applications 27 | with thousands of hosts frequently run into problems with flaky hosts or 28 | transient connectivity. These issues have little to do with the application 29 | logic. To address these types of problems, Envoy has two strategies for 30 | identifying failing infrastructure: Health Checking (active monitoring) and 31 | Outlier Detection (passive monitoring). 32 | 33 | ## Health Checking 34 | 35 | A healthy host is one that can respond positively to a request. Envoy can be 36 | configured to actively test hosts with 37 | [Health Checking](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/health_checking.html#arch-overview-health-checking), 38 | and it is defined on a per-[cluster](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/cds.proto) (i.e. service) 39 | basis. The simplest health check, or L3/L4 check, just ensures each 40 | [endpoint](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/endpoint/endpoint.proto) (i.e. port on a host or container) 41 | is available, and it doesn’t depend on any application logic. Because the IP 42 | and port are already specified as part of the endpoint, setting up a Health 43 | Check doesn’t even require service-specific information. 44 | 45 | A simple static YAML configuration may look like this: 46 | 47 | ```yaml 48 | health_checks: 49 | - timeout: 1s 50 | interval: 60s 51 | interval_jitter: 1s 52 | unhealthy_threshold: 3 53 | healthy_threshold: 3 54 | tcp_health_check: {} 55 | ``` 56 | 57 | Envoy also knows about HTTP, gRPC, and Redis protocols. For example, to test 58 | for a non-5xx response, replace `tcp_health_check` with `http_health_check`, 59 | which defines the URL to test: 60 | 61 | ```yaml 62 | host: "servicehost" 63 | path: "/health" 64 | service_name: "authentication" 65 | ``` 66 | 67 | With this strategy, you can implement logic for services that have a custom 68 | definition of “up”. While it’s easy to imagine writing comprehensive health 69 | checks that look for all possible problems with a host, the reality is that the 70 | check will never be full-fidelity. No matter how complex the active check is, 71 | there will be scenarios where it returns “success” and the host is failing. To 72 | figure out if a host is healthy enough to take traffic, it’s best to combine 73 | health checking with outlier detection. 74 | 75 | ## Outlier Detection 76 | 77 | Unlike active health checking, 78 | [Outlier Detection](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/outlier.html?highlight=outlier%20detection) 79 | —sometimes called passive health checking—uses the **responses from real 80 | requests to determine whether an endpoint is healthy**. Once an endpoint is 81 | removed, Envoy uses a time-out based approach for re-insertion, where unhealthy 82 | hosts are re-added to the cluster after a configurable interval. Each 83 | subsequent removal increases the interval, so a persistently unhealthy endpoint 84 | does as little damage as possible to user traffic. 85 | 86 | Like health checks, outlier detection is configured per-cluster. This 87 | configuration removes a host for 30 seconds when it returns 3 consecutive 5xx 88 | errors: 89 | 90 | ```yaml 91 | consecutive_5xx: "3" 92 | base_ejection_time: "30s" 93 | ``` 94 | 95 | When enabling outlier detection on a new service, it can help to start with a 96 | less stringent set of rules. A good place to start is to only eject hosts with 97 | gateway connectivity errors (HTTP 503), and only eject them 10% of the time. By 98 | ramping up the enforcement rate, you can avoid kicking a bunch of hosts out of 99 | a service for being flaky, which would potentially create more problems than it 100 | would solve: 101 | 102 | ```yaml 103 | consecutive_gateway_failure: "3" 104 | base_ejection_time: "30s" 105 | enforcing_consecutive_gateway_failure: "10" 106 | ``` 107 | 108 | On the other end of the spectrum, high-traffic, stable services can use 109 | statistics to eject hosts that are abnormally error-prone. This configuration 110 | would eject any endpoint whose error rate is more than 1 standard deviation 111 | below the average for the cluster. Note that this requires sustained traffic: 112 | the statistics are evaluated every 10 seconds, and the algorithm isn’t run for 113 | any host with fewer than 500 requests / 10 seconds. 114 | 115 | ```yaml 116 | interval: "10s" 117 | base_ejection_time: "30s" 118 | success_rate_minimum_hosts: "10" 119 | success_rate_request_volume: "500" 120 | success_rate_stdev_factor: "1000" # divided by 1000 to get a double 121 | ``` 122 | 123 | In all cases, the endpoints removed do not exceed the `max_ejection_percent` of 124 | the cluster, and they are re-inserted after their timeout 125 | (`base_ejection_time` * number of ejections) expires. 126 | 127 | ## Implementing Health Checking 128 | 129 | Health checking is one of the easiest ways to take advantage of Envoy’s ability 130 | to make your services more reliable—and you don't even have to write any new 131 | code. Remember that health checks are only for **host health**, and not 132 | **service health**. The goal is to auto-heal your service, not detect and fix 133 | bad code. 134 | 135 | To build a practical picture of host health, it’s best to combine both active 136 | and passive health checking. At scale, passive checks are more robust, so lean 137 | on them as the primary check. A good general strategy is to reject any endpoint 138 | with five 5xx responses in a row (outlier detection), or one that Envoy can’t 139 | proactively connect to (health checking). As mentioned above, if your service 140 | has enough traffic for it, statistical outlier detection is far more robust 141 | than simple consecutive errors. 142 | 143 | The above approach should work for most services, and it doesn’t require any 144 | new code. **Resist the urge to add complex active health checking, as these 145 | checks will never be perfect.** That said, there are three scenarios where 146 | adding a more complex health check will likely improve your results: 147 | 148 | If your service does **meaningful initialization work** that it performs 149 | **after it starts taking traffic**, an active health check can prevent a spike 150 | in errors when new hosts come online. In most cases, services with this 151 | behavior were simply never written to be immediately available and correct. 152 | Ideally, you’d fix the service to finish its initialization before serving 153 | traffic, but if that’s not possible, adding a health check can mitigate these 154 | transient errors. 155 | 156 | More broadly, if your system has a **custom definition of health** that isn’t 157 | easily derived from response data, an active health check can help. For 158 | instance, Cassandra auto-balances its data across all available hosts, so you 159 | could mark hosts under particularly heavy replication load unavailable for read 160 | requests. 161 | 162 | Finally, if the **amount of traffic is low but important**, an active health 163 | check can give you early warning that a host is misbehaving before a user 164 | connects. A service that updates payment information may only have a handful of 165 | requests a day, but because it has the possibility to charge a customer’s 166 | credit card, it’s difficult to use other resilience strategies like retries. 167 | Health checking makes sure all endpoints can get the necessary DB connections 168 | at all times, marking unreliable nodes as down before they make third-party 169 | calls. 170 | 171 | Logging ejections from the cluster will help you tune any rules you put in 172 | place and prevent hosts from flapping in and out of the cluster. 173 | 174 | For more details, see: 175 | 176 | - [Health Checking overview](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/health_checking.html#arch-overview-health-checking) in the Envoy docs 177 | - [Outlier Detection overview](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/cds.proto) in the Envoy docs 178 | - [Cluster configuration](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/cds.proto) in the Envoy docs 179 | -------------------------------------------------------------------------------- /_articles/incremental-deploys.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Incremental Deploys 4 | description: > 5 | Tutorial for getting Envoy running on your laptop as a load balancer that can 6 | handle releases via traffic shifting. Implement blue/green deploys and 7 | header-based routing against your own services with a local Docker container. 8 | --- 9 | 10 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 11 | [//]: # ( we may not use this file except in compliance with the License. ) 12 | [//]: # ( we may obtain a copy of the License at ) 13 | [//]: # ( ) 14 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 15 | [//]: # ( ) 16 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 17 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 18 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 19 | [//]: # ( implied. See the License for the specific language governing ) 20 | [//]: # ( permissions and limitations under the License. ) 21 | 22 | [//]: # (Incremental Deploys) 23 | 24 | # Incremental Blue/Green Deploys 25 | 26 | One of most common workflows for any microservice is releasing a new version. 27 | Thinking about releases as a traffic management problem—as opposed to an 28 | infrastructure update—opens up new tools for protecting users from bad releases. 29 | 30 | We’ll begin with the simple routes we set up previously 31 | [on your laptop](on-your-laptop.html). 32 | Next, we’ll extend that config to release a new version of one of the services 33 | using traffic shifting. We’ll also cover header-based routing and weighted load 34 | balancing to show how to use traffic management to canary a release, first to 35 | special requests (e.g. requests from your laptop), then to a small fraction of 36 | all requests. 37 | 38 | ## The setup 39 | 40 | For this guide, we’ll need: 41 | 42 | - [Docker](https://docs.docker.com/install/) 43 | - [Docker Compose](https://docs.docker.com/compose/install/) 44 | - [Git](https://help.github.com/articles/set-up-git/) 45 | - [curl](https://curl.haxx.se/) 46 | 47 | ## Header-based Routing 48 | 49 | First, we'll create a new version of service1 to illustrate the value of 50 | header-based routing for our services. Still following along with the 51 | [front-proxy](https://github.com/envoyproxy/envoy/tree/master/examples/front-proxy) 52 | example from the Envoy repo, modify the 53 | [docker-compose.yml](https://github.com/envoyproxy/envoy/blob/master/examples/front-proxy/docker-compose.yml) 54 | to spin up a new service, called `service1a`. 55 | 56 | ```yaml 57 | service1a: 58 | build: 59 | context: . 60 | dockerfile: Dockerfile-service 61 | volumes: 62 | - ./service-envoy.yaml:/etc/service-envoy.yaml 63 | networks: 64 | envoymesh: 65 | aliases: 66 | - service1a 67 | environment: 68 | - SERVICE_NAME=1a 69 | expose: 70 | - "80" 71 | ``` 72 | 73 | To make sure Envoy can discover this service, we’ll also add it to the 74 | `clusters` section of our configuration file. 75 | 76 | ```yaml 77 | - name: service1a 78 | connect_timeout: 0.25s 79 | type: strict_dns 80 | lb_policy: round_robin 81 | http2_protocol_options: {} 82 | hosts: 83 | - socket_address: 84 | address: service1a 85 | port_value: 80 86 | ``` 87 | 88 | To make this routable, we can add a new route with a `headers` field in the 89 | match. Since routing rules are applied in order, we’ll add this rule to the top 90 | of the `routes` key. Requests with a header that matches our new rule will be 91 | sent to our new service, while requests that don't include this header will 92 | still get service 1. 93 | 94 | ```yaml 95 | routes: 96 | - match: 97 | prefix: "/service/1" 98 | headers: 99 | - name: "x-canary-version" 100 | exact_match: "service1a" 101 | route: 102 | cluster: service1a 103 | - match: 104 | prefix: "/service/1" 105 | route: 106 | cluster: service1 107 | - match: 108 | prefix: "/service/2" 109 | route: 110 | cluster: service2 111 | ``` 112 | 113 | Shut down and then relaunch our example services with: 114 | 115 | ```console 116 | $ docker-compose down --remove-orphans 117 | ``` 118 | 119 | ```console 120 | $ docker-compose up --build -d 121 | ``` 122 | 123 | In a production Envoy deployment, configuration changes like this won’t require 124 | a restart of Envoy, but since we’re running everything locally, we aren’t able 125 | to take advantage of its dynamic configuration abilities. 126 | 127 | If we make a request to our service with no headers, we'll get a response 128 | from service 1: 129 | 130 | ```console 131 | $ curl localhost:8000/service/1 132 | ``` 133 | 134 | ```shell 135 | Hello from behind Envoy (service 1)! hostname: d0adee810fc4 resolvedhostname: 172.18.0.2 136 | ``` 137 | 138 | However if we include the `x-canary-version` header, Envoy will route our 139 | request to service 1a: 140 | 141 | ```console 142 | $ curl -H 'x-canary-version: service1a' localhost:8000/service/1 143 | ``` 144 | 145 | ```shell 146 | Hello from behind Envoy (service 1a)! hostname: 569ee89eebc8 resolvedhostname: 172.18.0.6 147 | ``` 148 | 149 | Header-based routing with Envoy unlocks the ability to 150 | [test development code in production](https://opensource.com/article/17/8/testing-production). 151 | 152 | ## Weighted Load Balancing 153 | 154 | Next, let's modify our config further to enable an incremental release to our 155 | new service version. The following config should look familiar, but we've 156 | swapped out the `cluster` key for `clusters` array under the default 157 | routing rule, which moves 25% of the traffic pointed at our service to this 158 | new version. 159 | 160 | ```yaml 161 | - match: 162 | prefix: "/service/1" 163 | route: 164 | weighted_clusters: 165 | clusters: 166 | - name: service1a 167 | weight: 25 168 | - name: service1 169 | weight: 75 170 | ``` 171 | 172 | With this in place, shut down your previous example services by running: 173 | 174 | ```console 175 | $ docker-compose down --remove-orphans 176 | ``` 177 | 178 | Then, start it again with: 179 | 180 | ```console 181 | $ docker-compose up --build -d 182 | ``` 183 | 184 | Now, if we make a request to our service with no headers we should see 185 | responses from service 1a about 25% of the time, or when the appropriate header 186 | is loaded. 187 | 188 | This example illustrates the power of an incremental release of your service, 189 | and in the wild would also be paired with monitoring to ensure the delta 190 | between versions of services, or between heterogeneous backends was trending 191 | well before increasing or completing a release. 192 | 193 | If we wanted to simulate a successful release, we could set the value of our 194 | rule to 100, which would ensure all traffic is now sent to service 1a instead 195 | of service 1. Similarly, by setting this value to 0, we could roll-back a bad 196 | release. 197 | 198 | ## Best practices 199 | 200 | With the basics of using header-based routing and incremental weighted release, 201 | you can now take advantage of a few best-practice patterns of software deploy 202 | and release. 203 | 204 | To start, separate the deploy and release processes. For most teams, this means 205 | using CI/CD to get new versions of software onto your infrastructure, but 206 | taking no traffic. Then release the software by incrementally shifting 207 | production traffic as described above. This can either be automated through 208 | CI/CD (after the deploy step), or run as a manual process. By separating these 209 | steps, you ensuring software on production infrastructure isn’t immediately 210 | production taking traffic, limiting the damage of a bad release. 211 | 212 | ## Wrap-up 213 | 214 | While not every release will require all of these capabilities, you can use 215 | Envoy’s routing tools to build a process to release software incrementally 216 | while gaining confidence in it. Once your new service is deployed, routing all 217 | internal traffic to it with a header will let your teams verify a PR, or 218 | internally test it. Once you think it’s ready for users, you can then use 219 | weighted incremental release patterns to gracefully release your new version to 220 | them. A good pattern for weights as you approach 100% of traffic starts small 221 | and takes progressively large leaps 1%, 5%, 10%, 50%. This pattern gives you 222 | actionable feedback on your release (watch the metrics after each adjustment!), 223 | with only small portions of your users initially affected. 224 | 225 | By separating deploy from release, using header-based routing to test 226 | production deploys before release, and building incremental release 227 | thoughtfully, your teams will greatly benefit from the capabilities of Envoy. 228 | 229 | Now that you've seen a few examples of incremental and header-based routing 230 | using Envoy, you may want to investigate more advanced features of Envoy, like 231 | [automatic retries](automatic-retries.html) 232 | or learn how to 233 | [dynamically configure routing](https://www.learnenvoy.io/articles/routing-configuration.html) 234 | -------------------------------------------------------------------------------- /_articles/on-your-laptop.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: On Your Laptop 4 | description: > 5 | In this article, we'll walk through how to run Envoy on your laptop, test 6 | proxy configurations, and observe results. Based on Docker and the official 7 | Envoy examples of a front proxy. 8 | --- 9 | 10 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 11 | [//]: # ( you may not use this file except in compliance with the License. ) 12 | [//]: # ( You may obtain a copy of the License at ) 13 | [//]: # ( ) 14 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 15 | [//]: # ( ) 16 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 17 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 18 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 19 | [//]: # ( implied. See the License for the specific language governing ) 20 | [//]: # ( permissions and limitations under the License. ) 21 | 22 | [//]: # (On Your Laptop) 23 | 24 | 25 | Before running Envoy in a production setting, you might want to tour its 26 | capabilities. In this article, we'll walk through how to run Envoy on your 27 | laptop, test proxy configurations, and observe results. 28 | 29 | ## Requirements 30 | 31 | While you can 32 | [build Envoy from source](https://www.envoyproxy.io/docs/envoy/v1.5.0/install/install), 33 | the easiest way to get started is by using the 34 | official [Docker images](https://hub.docker.com/u/envoyproxy/). So before 35 | starting out, you'll need the following software installed and configured: 36 | 37 | - [Docker](https://docs.docker.com/install/) 38 | - [Docker Compose](https://docs.docker.com/compose/install/) 39 | - [Git](https://help.github.com/articles/set-up-git/) 40 | - [curl](https://curl.haxx.se/) 41 | 42 | We use Docker and Docker Compose to set up and run example service topologies 43 | using Envoy, git to access the Envoy examples, and curl to send traffic to 44 | running services. 45 | 46 | ## Running Envoy 47 | 48 | Running the latest Docker image will technically get you Envoy on your laptop, 49 | but without a config file it won't do anything very interesting. Let's get a 50 | simple front proxy topology running, which will send traffic to two service 51 | backends. The [Envoy source repository](https://github.com/envoyproxy/envoy) has 52 | a couple of examples, so to start, clone that repository and go to the 53 | `examples/front-proxy` directory. This contains Dockerfiles, config files and a 54 | Docker Compose manifest for setting up a the topology. 55 | 56 | ```console 57 | $ git clone https://github.com/envoyproxy/envoy 58 | $ cd envoy/examples/front-proxy 59 | ``` 60 | 61 | The services run a very simple Flask application, defined in `service.py`. An 62 | Envoy runs in the same container as a sidecar, configured with the 63 | `service-envoy.yaml` file. Finally, the `Dockerfile-service` creates a container 64 | that runs Envoy and the service on startup. 65 | 66 | The front proxy is simpler. It runs Envoy, configured with the 67 | `front-envoy.yaml` file, and uses `Dockerfile-frontenvoy` as its container 68 | definition. 69 | 70 | The `docker-compose.yaml` file provides a description of how to build, package, 71 | and run the front proxy and services together. 72 | 73 | To build our containers, run: 74 | 75 | ```console 76 | $ docker-compose up --build -d 77 | ``` 78 | 79 | This starts a single instance of the front proxy and two service instances, one 80 | configured as "service1" and the other as "service2", `--build` means build 81 | containers before starting up, and `-d` means run them in detached mode. 82 | 83 | Running `docker-compose ps` should show the following output: 84 | 85 | ```console 86 | $ docker-compose ps 87 | ``` 88 | 89 | ```shell 90 | Name Command State Ports 91 | ---------------------------------------------------------------------------------------------------------------- 92 | frontproxy_front-envoy_1 /bin/sh -c /usr/local/bin/ ... Up 0.0.0.0:8000->80/tcp, 0.0.0.0:8001->8001/tcp 93 | frontproxy_service1_1 /bin/sh -c /usr/local/bin/ ... Up 80/tcp 94 | frontproxy_service2_1 /bin/sh -c /usr/local/bin/ ... Up 80/tcp 95 | ``` 96 | 97 | ## Sending Traffic 98 | 99 | Docker Compose has mapped port 8000 on the front-proxy to your local 100 | network. Open your browser to http://localhost:8000/service/1, or run `curl 101 | localhost:8000/service/1`. You should see 102 | 103 | ```console 104 | $ curl localhost:8000/service/1 105 | ``` 106 | 107 | ```shell 108 | Hello from behind Envoy (service 1)! hostname: 6632a613837e resolvedhostname: 172.19.0.3 109 | ``` 110 | 111 | Going to http://localhost:8000/service/2 should result in 112 | 113 | ```console 114 | $ curl localhost:8000/service/2 115 | ``` 116 | 117 | ```shell 118 | Hello from behind Envoy (service 2)! hostname: bf97b0b3294d resolvedhostname: 172.19.0.2 119 | ``` 120 | 121 | You're connecting to Envoy, operating as a front proxy, which is in turn sending 122 | your request to service 1 or service 2. 123 | 124 | ## Configuring Envoy 125 | 126 | This is a simple way to configure Envoy statically for the purpose of 127 | demonstration. As we move on, you'll see how you can really harness its power by 128 | dynamically configuring it. 129 | 130 | Let's take a look at how Envoy is configured. To get the right services set up, 131 | Docker Compose looks at the `docker-compose.yaml` file. You'll see the following 132 | definition for the `front-envoy` service: 133 | 134 | ```yaml 135 | front-envoy: 136 | build: 137 | context: ../ 138 | dockerfile: front-proxy/Dockerfile-frontenvoy 139 | volumes: 140 | - ./front-envoy.yaml:/etc/front-envoy.yaml 141 | networks: 142 | - envoymesh 143 | expose: 144 | - "80" 145 | - "8001" 146 | ports: 147 | - "8000:80" 148 | - "8001:8001" 149 | ``` 150 | 151 | Going from top to bottom, this says: 152 | 153 | 1. Build a container using the `Dockerfile-frontenvoy` file located in the 154 | current directory 155 | 2. Mount the `front-envoy.yaml` file in this directory as `/etc/front-envoy.yaml` 156 | 3. Create and use a Docker network named "`envoymesh`" for this container 157 | 4. Expose ports 80 (for general traffic) and 8001 (for the admin server) 158 | 5. Map the host port 8000 to container port 80, and the host port 8001 to 159 | container port 8001 160 | 161 | Knowing that our front proxy uses the `front-envoy.yaml` to configure Envoy, 162 | let's take a deeper look. Our file has two top level elements, 163 | `static_resources` and `admin`. 164 | 165 | ```yaml 166 | static_resources: 167 | admin: 168 | ``` 169 | 170 | The `admin` block is relatively simple. 171 | 172 | ```yaml 173 | admin: 174 | access_log_path: "/dev/null" 175 | address: 176 | socket_address: 177 | address: 0.0.0.0 178 | port_value: 8001 179 | ``` 180 | 181 | The `access_log_path` field is set to `/dev/null`, meaning access logs to the 182 | admin server are discarded. In a testing or production environment, users would 183 | change this value to an appropriate destination. The `address` object tells 184 | Envoy to create an admin server listening on port 8001. 185 | 186 | The `static_resources` block contains definitions for clusters and listeners 187 | that aren't dynamically managed. A cluster is a named group of hosts/ports, over 188 | which Envoy will load balance traffic, and listeners are named network locations 189 | that clients can connect to. The `admin` block configures our admin server. 190 | 191 | Our front proxy has a single listener, configured to listen on port 80, with 192 | a filter chain that configures Envoy to manage HTTP traffic. 193 | 194 | ```yaml 195 | listeners: 196 | - address: 197 | socket_address: 198 | address: 0.0.0.0 199 | port_value: 80 200 | filter_chains: 201 | - filters: 202 | - name: envoy.http_connection_manager 203 | config: 204 | codec_type: auto 205 | stat_prefix: ingress_http 206 | route_config: 207 | name: local_route 208 | ``` 209 | 210 | Within the configuration for our HTTP connection manager filter, there is a 211 | definition for a single virtual host, configured to accept traffic for all 212 | domains. 213 | 214 | ```yaml 215 | virtual_hosts: 216 | - name: backend 217 | domains: 218 | - "*" 219 | routes: 220 | - match: 221 | prefix: "/service/1" 222 | route: 223 | cluster: service1 224 | - match: 225 | prefix: "/service/2" 226 | route: 227 | cluster: service2 228 | ``` 229 | 230 | Routes are configured here, mapping traffic for `/service/1` and `/service/2` to 231 | the appropriate clusters. 232 | 233 | Next come static cluster definitions: 234 | 235 | ```yaml 236 | clusters: 237 | - name: service1 238 | connect_timeout: 0.25s 239 | type: strict_dns 240 | lb_policy: round_robin 241 | http2_protocol_options: {} 242 | hosts: 243 | - socket_address: 244 | address: service1 245 | port_value: 80 246 | - name: service2 247 | connect_timeout: 0.25s 248 | type: strict_dns 249 | lb_policy: round_robin 250 | http2_protocol_options: {} 251 | hosts: 252 | - socket_address: 253 | address: service2 254 | port_value: 80 255 | ``` 256 | 257 | You can configure timeouts, circuit breakers, discovery settings, and more on 258 | clusters. Clusters are composed of endpoints – a set of network locations that 259 | can serve requests for the cluster. In this example, endpoints are canonically 260 | defined in DNS, which Envoy can read from. Endpoints can also be defined 261 | directly as socket addresses, or read dynamically via 262 | the Endpoint Discovery Service. 263 | 264 | ### Modifying Configuration 265 | 266 | In Envoy, you can modify the config files, rebuild Docker images, and test the 267 | changes. Listener filters are Envoy's way of attaching additional functionality 268 | to listeners. For instance, to add access logging to your HTTP filter, add the 269 | `access_log` object to your filter config, as shown here. 270 | 271 | 272 | ```yaml 273 | - filters: 274 | - name: envoy.http_connection_manager 275 | config: 276 | codec_type: auto 277 | stat_prefix: ingress_http 278 | access_log: 279 | - name: envoy.file_access_log 280 | config: 281 | path: "/var/log/access.log" 282 | route_config: 283 | ``` 284 | 285 | 286 | Destroy your Docker Compose stack with `docker-compose down`, then rebuild it 287 | with `docker-compose up --build -d`. Make a few requests to your services using 288 | curl, then log into a shell with `docker-compose exec front-envoy /bin/bash`. An 289 | `access.log` file should be in `/var/log`, showing the results of your requests. 290 | 291 | ## Admin Server 292 | 293 | A great feature of Envoy is the built-in admin server. If you visit 294 | `http://localhost:8001` in your browser you should see a page with links to more 295 | information. The `/clusters` endpoint shows statistics on upstream clusters, and 296 | the `stats` endpoint shows more general statistics. You can get information 297 | about the server build at `/server_info`, query and alter logging levels at 298 | `/logging`. General help is available at the `/help` endpoint. 299 | 300 | ## Further Exploration 301 | 302 | If you're interested in exploring more of Envoy's capabilities, 303 | the [Envoy examples](https://github.com/envoyproxy/envoy/tree/master/examples) 304 | have more complex topologies that will get you slightly more real-world, but 305 | still use statically discovered examples. If you'd like to learn more about how 306 | to operate Envoy in a production setting, the 307 | [service discovery integration](./service-discovery.html) walks through what it 308 | means to integrate Envoy with your existing environment. If you run into issues 309 | as you begin to test out Envoy, be sure to visit 310 | [getting help](getting-help.html) to learn where to report issues, and who to 311 | message. 312 | -------------------------------------------------------------------------------- /_articles/routing-basics.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Routing Basics 4 | description: > 5 | In-depth tutorial on Envoy's routing on your laptop. See how to configure 6 | routes, clusters, and listeners with static files in this Docker-based 7 | example. 8 | --- 9 | 10 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 11 | [//]: # ( we may not use this file except in compliance with the License. ) 12 | [//]: # ( we may obtain a copy of the License at ) 13 | [//]: # ( ) 14 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 15 | [//]: # ( ) 16 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 17 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 18 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 19 | [//]: # ( implied. See the License for the specific language governing ) 20 | [//]: # ( permissions and limitations under the License. ) 21 | 22 | [//]: # (Routing Basics) 23 | 24 | # Routing Basics 25 | 26 | This article discusses Envoy's routing in more detail. You may have already 27 | seen how routing works 28 | [on your laptop](on-your-laptop.html) 29 | but now you can see more of how routes, clusters, and listeners are configured 30 | with static files. 31 | 32 | ## Routing components 33 | 34 | ### Route 35 | 36 | A route is a set of rules that match virtual hosts to clusters and allow you to 37 | create traffic shifting rules. Routes are configured either via static 38 | definion, or via the route discovery service (RDS). 39 | 40 | ### Cluster 41 | 42 | A cluster is a group of similar upstream hosts that accept traffic from Envoy. 43 | Clusters allow for load balancing of homogenous service sets, and better 44 | infrastructure resiliency. Clusters are configured either via static 45 | definitions, or by using the cluster discovery service (CDS). 46 | 47 | ### Listener 48 | 49 | A listener is a named network location (e.g., port, unix domain socket, etc.) 50 | that can accept connections from downstream clients. Envoy exposes one or more 51 | listeners. Listener configuration can be declared statically in the bootstrap 52 | config, or dynamically via the listener discovery service (LDS). 53 | 54 | ## Defining Routes 55 | 56 | Envoy’s routing definitions map a domain + URL to a cluster. In our previous 57 | tutorial 58 | [On Your Laptop](on-your-laptop.html), 59 | we defined a simple setup with 2 clusters (service1 and service2), each of 60 | which lived at a separate URL (/service1 and /service2). 61 | 62 | ```yaml 63 | virtual_hosts: 64 | - name: backend 65 | domains: 66 | - "*" 67 | routes: 68 | - match: 69 | prefix: "/service/1" 70 | route: 71 | cluster: service1 72 | - match: 73 | prefix: "/service/2" 74 | route: 75 | cluster: service2 76 | ``` 77 | 78 | Clusters pull their membership data from DNS and use a round-robin load 79 | balancing over all hosts. This cluster definition is from the examples 80 | [on your laptop](on-your-laptop.html). 81 | 82 | ```yaml 83 | clusters: 84 | - name: service1 85 | connect_timeout: 0.25s 86 | type: strict_dns 87 | lb_policy: round_robin 88 | http2_protocol_options: {} 89 | hosts: 90 | - socket_address: 91 | address: service1 92 | port_value: 80 93 | - name: service2 94 | connect_timeout: 0.25s 95 | type: strict_dns 96 | lb_policy: round_robin 97 | http2_protocol_options: {} 98 | hosts: 99 | - socket_address: 100 | address: service2 101 | port_value: 80 102 | ``` 103 | 104 | While example uses DNS for load balancing, but Envoy can also be configured to 105 | work with service discovery. 106 | 107 | ## Configuring listeners 108 | 109 | The following static configuration defines one listener, with some filters that 110 | map to two different services. These listeners are fairly simple, and also 111 | match to the services in our cluster and route definitions. 112 | 113 | ```yaml 114 | listeners: 115 | - address: 116 | socket_address: 117 | address: 0.0.0.0 118 | port_value: 80 119 | filter_chains: 120 | - filters: 121 | - name: envoy.http_connection_manager 122 | config: 123 | codec_type: auto 124 | stat_prefix: ingress_http 125 | route_config: 126 | name: local_route 127 | virtual_hosts: 128 | - name: backend 129 | domains: 130 | - "*" 131 | routes: 132 | - match: 133 | prefix: "/service/1" 134 | route: 135 | cluster: service1 136 | - match: 137 | prefix: "/service/2" 138 | route: 139 | cluster: service2 140 | http_filters: 141 | - name: envoy.router 142 | config: {} 143 | ``` 144 | 145 | ## Dynamic configuration of routes, clusters, and listeners 146 | 147 | The routes and clusters noted here are defined statically, but by using RDS and 148 | CDS to define them dynamically, you can centralize the route tables and cluster 149 | definitions, and listeners and apply the same rules to multiple envoys, easing 150 | the propagation of your changes on a large scale across your infrastructure. 151 | 152 | 153 | ## Further Exploration 154 | 155 | Defining routes and listeners is crucial for using Envoy to connect traffic to 156 | your services. Now that you understand basic configurations, you can see how 157 | more complex traffic-shifting works in Envoy during 158 | [incremental deploys and releases](incremental-deploys.html), 159 | or learn how to 160 | [configure routing with RDS](routing-configuration.html), 161 | the route discovery service. 162 | -------------------------------------------------------------------------------- /_articles/routing-configuration.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Routing with a Control Plane 4 | description: > 5 | Tips and tricks on how large companies configure Envoy's routing at scale. 6 | This article covers how to treat routes as data, distributing control across 7 | multiple teams, and what sort of changes are most common in distributed 8 | systems. 9 | --- 10 | 11 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 12 | [//]: # ( you may not use this file except in compliance with the License. ) 13 | [//]: # ( You may obtain a copy of the License at ) 14 | [//]: # ( ) 15 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 16 | [//]: # ( ) 17 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 18 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 19 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 20 | [//]: # ( implied. See the License for the specific language governing ) 21 | [//]: # ( permissions and limitations under the License. ) 22 | 23 | [//]: # (Routing with a Control Plane) 24 | 25 | When running a large Envoy fleet in production, it’s important to separate the 26 | data plane — user traffic — from the control plane, which includes Envoy 27 | configuration and infrastructure state. Setting up a simple control plane 28 | generally includes choosing configuration options like [automatic 29 | retries](automatic-retries.html) and integrating [service 30 | discovery](service-discovery.html). 31 | 32 | One of the biggest advantages of creating a distinct, centralized control plane 33 | is that it provides a source of truth for routing configuration. In legacy 34 | systems, this is stored in a mix of web server configuration files, load 35 | balancer configs, and application-specific routing definitions 36 | (e.g. `routes.rb`). Centralizing these definitions makes them safe and easy to 37 | change. This provides teams with flexibility during migrations, releases, and 38 | other major system changes. 39 | 40 | ## Serving Routes via RDS 41 | 42 | Envoy’s dynamic configuration allows these routing configurations to execute 43 | rules defined in a control plan with its Route Discovery Service, or 44 | [RDS](https://www.envoyproxy.io/docs/envoy/latest/configuration/http_conn_man/rds). The 45 | control plane holds a mapping between a domain + path and an Envoy “cluster.” 46 | The control plane serves config definitions via RDS, and the Envoy instances 47 | implement the actual traffic control. 48 | 49 | Here is a simple example of a route in RDS: 50 | 51 | ```yaml 52 | version_info: "0" 53 | resources: 54 | - "@type": type.googleapis.com/envoy.api.v2.RouteConfiguration 55 | name: local_route 56 | virtual_hosts: 57 | - name: local_service 58 | domains: ["*"] 59 | routes: 60 | - match: { prefix: "/" } 61 | route: { cluster: some_service } 62 | ``` 63 | 64 | Both open-source 65 | ([go-control-plane](https://github.com/envoyproxy/go-control-plane), [Istio 66 | Pilot](https://istio.io/docs/concepts/traffic-management/pilot.html)) and 67 | commercial ([Houston](http://turbinelabs.io/product)) implementations of RDS are 68 | available, or the Envoy docs define a 69 | [full RDS specification](https://www.envoyproxy.io/docs/envoy/latest/configuration/overview/v2_overview.html#v2-grpc-streaming-endpoints) 70 | for teams that want to roll their own. Keep in mind that the RDS specification 71 | is only the transport mechanism; how you manage the state is up to you, 72 | discussed in more detail below. 73 | 74 | ## Best Practices for Routing Definitions 75 | 76 | Because there may be thousands of Envoy instances in a large system, the control 77 | plane should be the source of truth for all routes. Requests can come directly 78 | from users, from internal services, or from different cloud regions. Because of 79 | this, it’s best to deploy Envoy to handle these diverse network topologies 80 | (e.g. as a front proxy for customer traffic plus a service mesh for internal 81 | traffic) and have them all behave similarly, no matter where the traffic comes 82 | from. 83 | 84 | In order to scale out a single system for routing definitions, there are three 85 | key principles to follow: 86 | 87 | 1. Treat routes as data, not config 88 | 2. Distribute control to teams with ACLs 89 | 3. Design for changes with audit logs and rollbacks 90 | 91 | ## #1: Treat routes as data 92 | 93 | Treating routes as data in a shared service **prevents conflicts**, provides the 94 | right starting point for **managing convergence times**, and **ensures 95 | semantically correct definitions**. While tools like Istio make it easy to write 96 | YAML-based routes, managing hundreds of routes across thousands of lines of YAML 97 | makes it difficult to prove that every definition is a valid route. It’s 98 | tempting to manage these text files with existing tools (e.g. version 99 | control). But, bad merges can create disastrous outages where routes are lost or 100 | incorrectly re-written by an API that can’t check anything more than whether the 101 | file parses correctly. 102 | 103 | Practically, porting web server config files to Envoy bootstrap config files is 104 | a natural first step to try out Envoy. In order to put this into production, 105 | it’s recommended to at least centralize these files behind a single service, 106 | using a reference xDS implementation like 107 | [go-control-plane](https://github.com/envoyproxy/go-control-plane). Allowing 108 | multiple teams to edit these configs (#2 and #3, below) becomes a fragile part 109 | of the system. Moving the source of truth behind an API allows concurrent 110 | updates and prevents many nonsensical updates to routing definitions. 111 | 112 | ## #2: Distribute control to teams 113 | 114 | Traffic management unlocks powerful workflows like **blue-green releases** and 115 | **incremental migrations**. This makes it practical (and safe) for service teams 116 | to **control the routes to the services they own**. Depending on your needs, you 117 | either want to hide routes outside of their area of responsibility (to prevent 118 | mis-clicks and accidents), or entirely prevent certain members from modifying 119 | routes. Most of the time, this process should mirror the permissions for your 120 | deployment process, as it’s a similar set of responsibilities. 121 | 122 | ## #3: Design for change 123 | 124 | Like infrastructure changes and code deploys, it’s vital to understand **when 125 | routes changed** and **who changed them**. Many teams have found that when they 126 | distribute responsibility for routing definition, the number of route changes 127 | increases. For clarity, they keep a log of who made these changes. While 128 | automating common route changes reduces overhead, it’s helpful to tag these 129 | actions with the person likely associated with the change. For example, 130 | automatic blue/green releases from master should be tagged with the person who 131 | merged the last branch. 132 | 133 | To be able to act on problems that come from routing changes, teams must know 134 | how to **generate the changes** between two points in time and how to **roll 135 | them back** if necessary. This isn’t only valuable when making further changes 136 | (just as git history is useful when writing new code), but it should also be 137 | exported to a centralized monitoring system. Having a diff of routing changes 138 | means that problematic change-sets can be rolled back, giving operators more 139 | tools to stabilize a system that’s misbehaving. 140 | -------------------------------------------------------------------------------- /_articles/service-discovery.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Integrating Service Discovery with Envoy 4 | description: > 5 | Integrating Envoy with service discovery such as Consul, Kubernetes, ECS, 6 | AWS EC2, Mesos, and more lets Envoy route to dynamically configured 7 | endpoints. See how to set it up, either from scratch or with existing 8 | open-source tools. 9 | --- 10 | 11 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 12 | [//]: # ( you may not use this file except in compliance with the License. ) 13 | [//]: # ( You may obtain a copy of the License at ) 14 | [//]: # ( ) 15 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 16 | [//]: # ( ) 17 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 18 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 19 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 20 | [//]: # ( implied. See the License for the specific language governing ) 21 | [//]: # ( permissions and limitations under the License. ) 22 | 23 | [//]: # (Integrating Service Discovery with Envoy) 24 | 25 | One of the core concepts when setting up Envoy in production is separating the 26 | [data plane](https://blog.envoyproxy.io/service-mesh-data-plane-vs-control-plane-2774e720f7fc)— 27 | the Envoy instances that route your traffic—from the 28 | [control plane](https://blog.envoyproxy.io/service-mesh-data-plane-vs-control-plane-2774e720f7fc), 29 | which acts as the source of truth for the current state of your infrastructure 30 | and your desired configuration. 31 | 32 | You can start with a static config file as a control plane, but in most cases, 33 | teams quickly move from a static config file to an API service. Centralizing 34 | configuration in a service makes updates more reliable, taking advantage of 35 | Envoy’s ability to query for new configuration and reload it on the fly. The 36 | first step in setting up your control plane is connecting your service 37 | discovery. This is generally broken down into three steps: 38 | 39 | 1. Decide on a control plane implementation 40 | 2. Publish service definitions to Envoy clusters 41 | 3. Publish hosts/containers/instances to Envoy endpoints 42 | 43 | ## Control Plane Implementation 44 | 45 | Any control plane should implement the 46 | [Envoy v2 xDS APIs](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api). 47 | For the purpose of publishing service discovery data, you’ll need to implement 48 | the Cluster Discovery Service 49 | [(CDS)](https://www.envoyproxy.io/docs/envoy/latest/configuration/cluster_manager/cds.html) 50 | and the Endpoint Discovery Service 51 | [(EDS)](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/eds.proto). 52 | Here are several options to avoid starting from scratch: 53 | 54 | [Rotor](https://github.com/turbinelabs/rotor) is a **fast, lightweight xDS 55 | implementation with service discovery integration** to Kubernetes, Consul, AWS, 56 | and more. It provides a set of defaults for routing and listeners (RDS and 57 | LDS). It’s also part of the commercial solution 58 | [Houston, by Turbine Labs](https://turbinelabs.io), which adds more 59 | configuration around routing, resilience, and metrics. 60 | 61 | The Envoy repository provides 62 | [go-control-plane](https://github.com/envoyproxy/go-control-plane), an 63 | **open-source stub implementation**. If you want to get your hands dirty with 64 | exactly how everything is pulled from service discovery, cached locally, and 65 | served, this is a great starting point. 66 | 67 | If you’re running in Kubernetes, the 68 | [Istio project](https://istio.io/docs/concepts/traffic-management/pilot.html) 69 | has a **control plane implementation called Pilot**. It takes YAML files and 70 | turns them into xDS responses. Don’t be scared by the scope of Istio — Pilot 71 | can be used separately to configure Envoy, without pulling in all the other 72 | services like Mixer. 73 | 74 | ## Publish Services to CDS 75 | 76 | In Envoy’s vernacular, a “cluster” is a named group of hosts/ports, over which 77 | it will load balance traffic. You may call clusters services, microservices, or 78 | APIs. Envoy will periodically poll the CDS endpoint for cluster configuration, 79 | and expects a response like: 80 | 81 | ```yaml 82 | version_info: "0" 83 | resources: 84 | - "@type": type.googleapis.com/envoy.api.v2.Cluster 85 | name: some_service 86 | connect_timeout: 1.0s 87 | lb_policy: ROUND_ROBIN 88 | type: EDS 89 | eds_cluster_config: 90 | eds_config: 91 | api_config_source: 92 | api_type: GRPC 93 | cluster_names: [xds_cluster] 94 | ``` 95 | 96 | Each service collected by your service discovery maps to one item under 97 | “resources.” There are a few additional bits of information that are specific 98 | to load balancing in Envoy that you’ll need to set: 99 | 100 | `lb_policy` sets the type of load balancing. See what Envoy supports in the 101 | docs. 102 | 103 | `connect_timeout` sets the connection timeout. Lower is better: start with 1 104 | second, and raise it if you’re getting flapping due to network latency. 105 | 106 | `api_type` sets the protocol for the service, which your service discovery may 107 | not store directly. Envoy needs to know this to check connections. 108 | 109 | It’s possible to hardcode the list of endpoints, though if your infrastructure 110 | is dynamic, you’ll want to set “type” to EDS, which tells Envoy to poll the EDS 111 | API for a list of available IP/ports. 112 | 113 | For the full specifications, see the 114 | [Envoy docs](https://www.envoyproxy.io/docs/envoy/latest/api-v1/cluster_manager/cluster.html). 115 | Once this is configured, you can populate the endpoints that serve traffic for 116 | this cluster. 117 | 118 | ## Publish instances to EDS 119 | 120 | Envoy defines an “endpoint” as an IP and port available within a cluster. In 121 | order to balance traffic across a service, Envoy expects the API to provide a 122 | list of endpoints for each service. Envoy periodically polls the EDS endpoint, 123 | generating a response: 124 | 125 | ```yaml 126 | version_info: "0" 127 | resources: 128 | - "@type": type.googleapis.com/envoy.api.v2.ClusterLoadAssignment 129 | cluster_name: some_service 130 | endpoints: 131 | - lb_endpoints: 132 | - endpoint: 133 | address: 134 | socket_address: 135 | address: 127.0.0.2 136 | port_value: 1234 137 | ``` 138 | 139 | This is simpler than defining clusters, because the only thing Envoy needs to 140 | know is which cluster(s) this endpoint belongs to. 141 | 142 | Envoy treats CDS/EDS service discovery as advisory and eventually consistent; 143 | if traffic to an endpoint fails too often, the endpoint is removed from the 144 | load balancer until healthy again. There’s no need to aggressively remove 145 | endpoints from clusters if they’re unhealthy. **Envoy does that for you!** 146 | 147 | ## Best Practice: Partition your Configs 148 | 149 | If you have a lot of services, you’ll find that the responses from CDS and EDS 150 | are fairly overwhelming. Envoy can handle them, but if something goes wrong, 151 | making sense of a 5,000-line API response can be quite challenging. The 152 | industry standard is to partition your configs in two ways: 153 | 154 | - **Partition by datacenter / region.** In general, services in one datacenter 155 | don’t need to know about the exact endpoint available in other datacenters. To 156 | set up a trickle of traffic between regions (“backhaul,” making the service 157 | robust to region-specific failures), add the remote datacenter’s front proxy to 158 | the local load balancer. 159 | 160 | - **Partition by service need.** While generally not feasible for an initial 161 | roll-out, the most sophisticated Envoy deployments limit intra-service 162 | communication by only configuring Envoy sidecars to talk to a whitelist of 163 | services. This helps manage the complexity of having 1,000 microservices talk 164 | to each other at any time. It also provides some security protection by 165 | preventing services from making unexpected calls. 166 | 167 | In general, partitioning configuration makes it easier to operate both the 168 | Envoy fleet and individual services, at the expense of making the control plane 169 | more complex. Since the control plane isn’t in the critical path of customer 170 | requests, this tends to be a net win for overall system resilience. Many 171 | organizations have reported process wins by making the routing configs 172 | (discussed in the next section) partitioned and self-service, as well. 173 | 174 | ## Next Steps: Set up Routing 175 | 176 | Once your control plane knows about all the available services, it’s time to 177 | configure the routes on top of those services. Learn how to set up the Route 178 | Discovery Service 179 | [here](https://www.envoyproxy.io/docs/envoy/latest/configuration/http_conn_man/rds.html#config-http-conn-man-rds). 180 | -------------------------------------------------------------------------------- /_articles/service-mesh.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Service Mesh 4 | description: > 5 | A Service Mesh uses sidecars to handle outbound traffic for each service 6 | instance. This allows Envoy to handle load balancing and resilience 7 | strategies for all internal calls, as well as providing a coherent layer for 8 | observability. 9 | --- 10 | 11 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 12 | [//]: # ( you may not use this file except in compliance with the License. ) 13 | [//]: # ( You may obtain a copy of the License at ) 14 | [//]: # ( ) 15 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 16 | [//]: # ( ) 17 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 18 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 19 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 20 | [//]: # ( implied. See the License for the specific language governing ) 21 | [//]: # ( permissions and limitations under the License. ) 22 | 23 | [//]: # (Service Mesh) 24 | 25 | The recent popularity of microservices has made the need for safe, reliable 26 | service-to-service communication more apparent than ever. Envoy’s lightweight 27 | footprint, powerful routing constructs, and flexible observability support make 28 | it a great proxy to build a service mesh on. In this configuration, Envoy acts 29 | as the primary load balancer for requests between internal services. Managing 30 | this public traffic—also called “East/West” traffic—is trivial in an 31 | environment with a small number of services, but with tens or hundreds of 32 | services making calls to one another, it’s combinatorially more complex. 33 | 34 | That's where the Envoy service mesh comes in. This is a complementary 35 | deployment to a [Front Proxy](front-proxy.html), where Envoy handles traffic 36 | from the outside world (aka north-south traffic). 37 | 38 | A basic Service Mesh uses Envoy sidecars to handle outbound traffic for each 39 | service instance. This allows Envoy to handle load balancing and resilience 40 | strategies for all internal calls, as well as providing a coherent layer for 41 | observability. Services are still exposed to the internal network, and all 42 | network calls pass through an Envoy on `localhost`. Rolling out a basic Service 43 | Mesh can be done one service at a time, making it a practical first step for 44 | most Envoy deployments. 45 | 46 | ## Envoy as a Sidecar 47 | 48 | ### Kubernetes 49 | 50 | Kubernetes makes adding Envoy sidecars easy. You’ll need to do two things: 51 | 52 | 1. Add an Envoy container to your Pod spec 53 | 2. Modify your services to send all outbound traffic to this sidecar 54 | 55 | How you want to configure Envoy will vary depending on your environment—more on 56 | that below. If you want to use fully dynamic configuration, you can use a 57 | container like [envoy-simple](https://github.com/turbinelabs/envoy-simple) and 58 | set the location of the 59 | [various](service-discovery.html) 60 | [configuration services](routing-configuration.html) with 61 | environment variables. 62 | 63 | ```yaml 64 | - image: turbinelabs/envoy-simple:0.17.2 65 | imagePullPolicy: Always 66 | name: envoy-simple 67 | ports: 68 | - containerPort: 8000 69 | env: 70 | - name: ENVOY_XDS_HOST 71 | value: "rotor.default.svc.cluster.local" 72 | - name: ENVOY_XDS_PORT 73 | value: "50000" 74 | ``` 75 | 76 | Since Pods share the same notion of localhost, you can simply change your 77 | service to have them call localhost on port 8000 with the correct Host header 78 | set, instead of calling the remote service. If you’re using Kubernetes’ 79 | Services, you can override the environment variables (e.g. 80 | `SERVICENAME_SERVICE_HOST` and `SERVICENAME_SERVICE_PORT`) or Kubernetes’ DNS 81 | with your Envoy’s listener value. 82 | 83 | ### Other Environments 84 | 85 | Outside of Kubernetes, you have much more flexibility in how you deploy Envoy. 86 | You can run either the Envoy container or the binary on your hosts. Similar to 87 | Kubernetes, by running Envoy on localhost, you only have to change your 88 | services to communicated with Envoy on the port you specify. 89 | 90 | Docker, listening on port 8000: 91 | 92 | ```shell 93 | $ docker run -d \ 94 | -e 'ENVOY_XDS_HOST=127.0.0.1' \ 95 | -e 'ENVOY_XDS_PORT=50000' \ 96 | -p 8000:8000 \ 97 | turbinelabs/envoy-simple:0.17.2 98 | ``` 99 | 100 | Next, you should modify your services to route through Envoy. If changing their 101 | configuration or code isn’t possible, you can force all outbound traffic 102 | through Envoy with something like /etc/hosts or iptables. 103 | 104 | ## Sidecar Configuration 105 | 106 | The easiest way to get started is to have Envoy handle traffic just the name as 107 | your internal network does. Practically, this means three things: 108 | 109 | - **Expose a single listener for your services to send outbound traffic to.** 110 | This matches with the port exposed on your container, e.g. 8000 in the ex 111 | ample configs above. Inbound traffic skips Envoy and continues to talk 112 | directly to the services. Adding a listener to handle incoming traffic will 113 | be covered in Advanced Service Mesh (coming soon!). 114 | 115 | - **Serve the full route table in all sidecars**. B By exposing all services 116 | to all other services, you’ll ensure nothing breaks on the first iteration. 117 | If you have a [Front Proxy](front-proxy.html), re-using these routes can save 118 | time. If not, it’s straightforward to create a 119 | [basic set of routes and listeners](routing-basics.html) in a static Envoy 120 | configuration file. Once that’s working in production, it may make sense to 121 | limit the routes available for each service. The explicit routing between 122 | services helps service teams understand where their internal traffic is 123 | coming from, helping them define mutual SLOs. 124 | 125 | - **Consider using dynamic configuration for instance discovery in the first iteration**. Specifically, using 126 | [EDS to update Envoy’s notion of available hosts](service-discovery.html) 127 | with an EDS server like [Rotor](https://github.com/turbinelabs/rotor) keeps 128 | Envoy’s routing tables in sync with the underlying infrastructure. Envoy can 129 | use static configuration for listeners and routes, so it’s simple and 130 | valuable to set up a control plane to manage instance availability. 131 | 132 | If you’ve been following the examples above, you can set up 133 | [Rotor](https://github.com/turbinelabs/rotor), an Envoy control plane and 134 | service discovery bridge, to implement xDS. Remember that Envoy can mix static 135 | and dynamic configuration, so if you want to statically configure listeners, 136 | routes, and clusters (LDS / RDS / CDS), you can use your own Envoy container 137 | with a static config file while still using a dynamic EDS control plane. 138 | Eventually, there are [good reasons](routing-configuration.html) 139 | to move to a fully dynamic system. 140 | 141 | ## Observability 142 | 143 | One of the biggest benefits of a service mesh is that it provides a uniform 144 | view over your services. Each service will certainly have metrics and tooling 145 | unique to it, but Envoy provides a simple way to get the same high-level 146 | metrics for all services. Keep the following principles in mind when deciding 147 | which metrics to look at: 148 | 149 | - **Pick metrics that relate to customer experience**. IIn particular, Envoy 150 | can generate request volume, request rate, and latency histograms. Resource 151 | metrics like number of connections or amount of network traffic can mean 152 | different things on different services. See how 153 | [Lyft does it here](https://blog.envoyproxy.io/lyfts-envoy-dashboards-5c91738816b1). 154 | 155 | - **Segmentation of simple metrics, not more types of metrics.** 156 | Envoy can produce a stunning number of metrics. Teams with lots of services 157 | tend to get more value out of a small set of metrics, segmented by service, 158 | instance, and region 159 | 160 | - **Add tracing in Envoy.** Since Envoy is present at every network hop, it’s 161 | guaranteed to capture all intra-instance communication. This means that a 162 | single configuration can produce complete traces across the entire mesh. 163 | That’s a powerful framework to add more detailed custom instrumentation. 164 | _Note: you will have to propagate headers through each service to create full 165 | traces._ 166 | 167 | ## Multiple Regions 168 | 169 | As described in [Front Proxy](front-proxy.html), you should have one front 170 | proxy per datacenter. When setting up a mesh, it’s generally safer to send 171 | intra-data center traffic to the remote front proxy, instead of exposing all of 172 | the internals to all datacenters. This can simplify incident management as 173 | well, because changes to a single region are less likely to affect other 174 | regions. 175 | 176 | This also means you should split up the configs. Generally you can do this by 177 | running a different control plane in each data center. If you want to run a 178 | single control plane, check out the discussion of Locality in Advanced Service 179 | Mesh (coming soon!). 180 | 181 | In this setup, you would still map each service to a single Envoy cluster, but 182 | instead of including the remote instances, you’d include the remote front proxy 183 | as the out-of-zone instance in the cluster. 184 | 185 | ## Next Steps 186 | 187 | While this article has focused on how to handle traffic between services, it's 188 | also possible for Envoy to handle traffic from the public internet 189 | (“North/South” traffic) as a 190 | [Front Proxy](front-proxy.html). The service mesh and 191 | front proxy have a lot of overlapping features, so it can be useful to consider 192 | how to roll them both out. 193 | 194 | Beyond that, you can set up Envoy to also handle incoming traffic on each node 195 | within your service mesh. This gives better isolation between services and 196 | better observability. 197 | -------------------------------------------------------------------------------- /_articles/ssl.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: article 3 | title: Setting Up SSL in Envoy 4 | description: > 5 | A tutorial on terminating SSL / TLS with Envoy, including example 6 | configuration for both service meshes and public load balancers, as well as 7 | a guide for forcing insecure traffic to HTTPS. 8 | --- 9 | 10 | [//]: # ( Copyright 2018 Turbine Labs, Inc. ) 11 | [//]: # ( you may not use this file except in compliance with the License. ) 12 | [//]: # ( You may obtain a copy of the License at ) 13 | [//]: # ( ) 14 | [//]: # ( http://www.apache.org/licenses/LICENSE-2.0 ) 15 | [//]: # ( ) 16 | [//]: # ( Unless required by applicable law or agreed to in writing, software ) 17 | [//]: # ( distributed under the License is distributed on an "AS IS" BASIS, ) 18 | [//]: # ( WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ) 19 | [//]: # ( implied. See the License for the specific language governing ) 20 | [//]: # ( permissions and limitations under the License. ) 21 | 22 | [//]: # (Setting Up SSL with Envoy) 23 | 24 | When serving any kind of traffic over the public internet, it’s best to secure 25 | it. When used as either a front proxy or a service mesh proxy, Envoy supports 26 | TLS and SSL to encrypt all communication between clients and the proxy. 27 | 28 | In this article, we’ll show how to set up Envoy as a front proxy that 29 | terminates TLS. It builds off the code in On Your Laptop, which balances a 30 | single domain over two services. We’ll extend this to secure traffic to both 31 | services. 32 | 33 | There are three steps to get this running: 34 | 35 | 1. Specifying the certificate for Envoy to use 36 | 2. Envoy for TLS 37 | 3. Configuring Envoy to redirect insecure traffic 38 | 39 | ## Certificate Files 40 | 41 | To deploy this to production, you’ll need the certificate for the site you own. 42 | If you don’t already have this, [Let’s Encrypt](https://letsencrypt.org) 43 | provides free and automatable certificates. For testing, you can generate a 44 | private key file `example-com.key` and self-signed certificate `example-com.crt` 45 | using OpenSSL. The only important detail it will as you for is the Common 46 | Name. We’ll use `example.com`: 47 | 48 | ```console 49 | $ openssl req -x509 -newkey rsa:4096 -keyout example-com.key -out example-com.crt -days 365 50 | ``` 51 | 52 | ```shell 53 | Generating a 2048 bit RSA private key 54 | ...........................+++ 55 | ...............+++ 56 | writing new private key to 'mine2.key' 57 | ----- 58 | You are about to be asked to enter information that will be incorporated 59 | into your certificate request. 60 | What you are about to enter is what is called a Distinguished Name or a DN. 61 | There are quite a few fields but you can leave some blank 62 | For some fields there will be a default value, 63 | If you enter '.', the field will be left blank. 64 | ----- 65 | Country Name (2 letter code) []:US 66 | State or Province Name (full name) []:CA 67 | Locality Name (eg, city) []:SF 68 | Organization Name (eg, company) []:Turbine Labs 69 | Organizational Unit Name (eg, section) []:Envoy Division 70 | Common Name (eg, fully qualified host name) []:example.com 71 | Email Address []:you@example.com 72 | ``` 73 | 74 | You’ll have to put these somewhere that Envoy can get to them. Since we’re 75 | using Docker and docker-compose in this example, we’ll just add these to our 76 | Envoy container by modifying `Dockerfile-frontenvoy`: 77 | 78 | ```console 79 | ADD ./example-com.crt /etc/example-com.crt 80 | ADD ./example-com.key /etc/example-com.key 81 | ``` 82 | 83 | Since TLS configured via Envoy listeners, we’ll add a `tls_context` block next 84 | to our list of filters with the locations of these files in `front-envoy.yaml`: 85 | 86 | ```yaml 87 | tls_context: 88 | common_tls_context: 89 | tls_certificates: 90 | - certificate_chain: 91 | filename: "/etc/example-com.crt" 92 | private_key: 93 | filename: "/etc/example-com.key" 94 | ``` 95 | 96 | This will affect all traffic, and while this will work on any port, we should 97 | also change this listener to the standard TLS port, 443. 98 | 99 | ```yaml 100 | - address: 101 | socket_address: 102 | address: 0.0.0.0 103 | port_value: 443 104 | ``` 105 | 106 | Finally, we also have to specify the domain to serve traffic on instead of using 107 | a wildcard match. 108 | 109 | ```yaml 110 | domains: 111 | - "example.com" 112 | ``` 113 | 114 | Note that Envoy supports SNI for multiple domains (e.g. example.com and 115 | www.example.com) by essentially repeating this configuration across several 116 | filter chains within the same listener. You can see an example 117 | [in the Envoy docs](https://www.envoyproxy.io/docs/envoy/latest/faq/sni). At 118 | the moment (Envoy v1.6), these filter chains must be identical across domains. 119 | Copy/paste away! 120 | 121 | To expose this to the world, we'll have to modify our `docker-compose.yaml` file 122 | to expose port 443. Also, we'll replace port 8080 with port 80, just to mimic a 123 | typical setup. 124 | 125 | ```yaml 126 | services: 127 | front-envoy: 128 | ... 129 | expose: 130 | - "80" 131 | - "443" 132 | ports: 133 | - "80:80" 134 | - "443:443" 135 | ``` 136 | 137 | You can test that this works with curl. Two notes if you’re using the 138 | self-signed certs from above: 139 | 140 | - To get curl to successfully validate the certificate, we have to pass the 141 | certificate file to Envoy. We do this with the `--cacert` option. 142 | - To get curl to connect to our Envoy instead of asking the system to resolve 143 | example.com, we have to explicitly specify that we’re connecting to 144 | localhost. We do this with the `--connect-to` option. If your version of curl 145 | does not support this option, you can add an entry to your `/etc/hosts` file 146 | to redirect `example.com` to `127.0.0.1`. 147 | 148 | ```console 149 | $ docker-compose build 150 | $ docker-compose up 151 | $ curl --cacert example-com.crt --connect-to localhost -H 'Host: example.com' https://localhost/service/1 152 | Hello from behind Envoy (service 1)! hostname: 56e8a5bff6bd resolvedhostname: 172.18.0.2 153 | ``` 154 | 155 | ## Redirecting Insecure Traffic 156 | 157 | We’re now serving TLS traffic in a narrow sense, but we’re not serving anything 158 | on plain old HTTP/80, which would confuse most clients. We could duplicate our 159 | routing configuration to serve both versions, but it’s better to redirect all 160 | insecure traffic to the TLS version of our site. We can do this with a separate 161 | listener and static routing configuration: 162 | 163 | The whole thing looks like: 164 | 165 | ```yaml 166 | - address: 167 | socket_address: 168 | address: 0.0.0.0 169 | port_value: 80 170 | filter_chains: 171 | - filters: 172 | - name: envoy.http_connection_manager 173 | config: 174 | codec_type: auto 175 | stat_prefix: ingress_http 176 | route_config: 177 | virtual_hosts: 178 | - name: backend 179 | domains: 180 | - "example.com" 181 | routes: 182 | - match: 183 | prefix: "/" 184 | redirect: 185 | path_redirect: "/" 186 | https_redirect: true 187 | http_filters: 188 | - name: envoy.router 189 | config: {} 190 | ``` 191 | 192 | You can test this with curl, and it will return a 301: 193 | 194 | ```console 195 | $ docker-compose build 196 | $ docker-compose up 197 | ``` 198 | 199 | ```console 200 | $ curl -I -H 'Host: example.com' http://localhost/service/1 201 | ``` 202 | 203 | ```shell 204 | HTTP/1.1 301 Moved Permanently 205 | location: https://example.com/ 206 | date: Fri, 25 May 2018 22:17:24 GMT 207 | server: envoy 208 | content-length: 0 209 | ``` 210 | 211 | That’s it, you’re done! The front-envoy.yaml file is included here: 212 | 213 | ```yaml 214 | static_resources: 215 | listeners: 216 | - address: 217 | socket_address: 218 | address: 0.0.0.0 219 | port_value: 80 220 | filter_chains: 221 | - filters: 222 | - name: envoy.http_connection_manager 223 | config: 224 | codec_type: auto 225 | stat_prefix: ingress_http 226 | route_config: 227 | virtual_hosts: 228 | - name: backend 229 | domains: 230 | - "example.com" 231 | routes: 232 | - match: 233 | prefix: "/" 234 | redirect: 235 | path_redirect: "/" 236 | https_redirect: true 237 | http_filters: 238 | - name: envoy.router 239 | config: {} 240 | - address: 241 | socket_address: 242 | address: 0.0.0.0 243 | port_value: 443 244 | filter_chains: 245 | - filters: 246 | - name: envoy.http_connection_manager 247 | config: 248 | codec_type: auto 249 | stat_prefix: ingress_http 250 | route_config: 251 | name: local_route 252 | virtual_hosts: 253 | - name: backend 254 | domains: 255 | - "example.com" 256 | routes: 257 | - match: 258 | prefix: "/service/1" 259 | route: 260 | cluster: service1 261 | - match: 262 | prefix: "/service/2" 263 | route: 264 | cluster: service2 265 | http_filters: 266 | - name: envoy.router 267 | config: {} 268 | tls_context: 269 | common_tls_context: 270 | tls_certificates: 271 | - certificate_chain: 272 | filename: "/etc/example-com.crt" 273 | private_key: 274 | filename: "/etc/example-com.key" 275 | clusters: 276 | - name: service1 277 | connect_timeout: 0.25s 278 | type: strict_dns 279 | lb_policy: round_robin 280 | http2_protocol_options: {} 281 | hosts: 282 | - socket_address: 283 | address: service1 284 | port_value: 80 285 | - name: service2 286 | connect_timeout: 0.25s 287 | type: strict_dns 288 | lb_policy: round_robin 289 | http2_protocol_options: {} 290 | hosts: 291 | - socket_address: 292 | address: service2 293 | port_value: 80 294 | admin: 295 | access_log_path: "/dev/null" 296 | address: 297 | socket_address: 298 | address: 0.0.0.0 299 | port_value: 8001 300 | ``` 301 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Jekyll! 2 | # 3 | # This config file is meant for settings that affect your whole blog, values 4 | # which you are expected to set up once and rarely edit after that. If you find 5 | # yourself editing this file very often, consider using Jekyll's data files 6 | # feature for the data you need to update frequently. 7 | # 8 | # For technical reasons, this file is *NOT* reloaded automatically when you use 9 | # 'bundle exec jekyll serve'. If you change this file, please restart the server process. 10 | 11 | # Site settings 12 | # These are used to personalize your new site. If you look in the HTML files, 13 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. 14 | # You can create any custom variable you would like, and they will be accessible 15 | # in the templates via {{ site.myvariable }}. 16 | title: LearnEnvoy 17 | email: learnenvoy@turbinelabs.io 18 | support_email: learnenvoy@turbinelabs.io 19 | description: > # this means to ignore newlines until "baseurl:" 20 | LearnEnvoy is a community content site that helps organizations get the most 21 | out of the Envoy proxy 22 | baseurl: "" # the subpath of your site, e.g. /blog 23 | url: "https://www.learnenvoy.io" 24 | twitter_username: goturbine 25 | github_username: turbinelabs 26 | 27 | # Build settings 28 | markdown: redcarpet 29 | redcarpet: 30 | extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "tables", "with_toc_data"] 31 | theme: agency-jekyll-theme 32 | 33 | collections: 34 | articles: 35 | output: true 36 | 37 | exclude: 38 | - Gemfile 39 | - Gemfile.lock 40 | - CODE_OF_CONDUCT.md 41 | - LICENSE 42 | - README.md 43 | - vendor/bundler 44 | - node_modules 45 | - Makefile 46 | sass: 47 | style: compressed 48 | load_paths: 49 | - _sass 50 | - node_modules 51 | 52 | gems: 53 | - jekyll-sitemap 54 | -------------------------------------------------------------------------------- /_data/building-on.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Turbine Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - name: "Incremental Blue/Green Deploys" 16 | icon: "code-branch" 17 | description: "Separate deploy from release. First, deploy new versions without taking traffic. Then, shift 1% of traffic over to the new version and check the metrics. If everything looks good, try 10%, 50%, 100%. It takes all of the stress out of releasing." 18 | article: incremental-deploys.html 19 | 20 | - name: "Verifying in Production" 21 | icon: "thumbs-up" 22 | description: "Stop trying to run all 5,000 microservices on your laptop. You don’t have enough RAM. You’ll never have enough RAM." 23 | 24 | - name: "Migrations" 25 | icon: "angle-double-right" 26 | description: "Moving to Kubernetes? Going multi-cloud? Deconstructing your monolith? Run traffic to both versions simultaneously and capture metrics as you build." 27 | -------------------------------------------------------------------------------- /_data/deployment-models.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Turbine Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - name: "Front Proxy" 16 | icon: "download" 17 | description: "How do you get traffic into your service from the internet? Envoy can take care of terminating SSL, translating traffic from HTTP1.1 to HTTP/2, and more." 18 | article: front-proxy.html 19 | 20 | - name: "Service Mesh" 21 | icon: "arrows-alt" 22 | description: "By co-locating Envoy with your code, you can let Envoy handle the complexities of the network. This makes service-to-service communication safer and more reliable, while alleviating the need to re-implement this functionality within each service." 23 | article: service-mesh.html 24 | 25 | - name: "Hosted Where You Are" 26 | icon: "server" 27 | description: "Use your existing deployment and production tooling to get Envoy on your infrastructure. There’s no need to reinvent the wheel to put Envoy in place as a front proxy or sidecar." 28 | -------------------------------------------------------------------------------- /_data/dynamic-configuration.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Turbine Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - name: "Service Discovery Integration" 16 | icon: "cogs" 17 | description: "No more hard-coding IP addresses and ports. [CDS](https://www.envoyproxy.io/docs/envoy/latest/configuration/cluster_manager/cds.html) and [EDS](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/eds.proto.html) let you integrate with your service registry to automatically populate which hosts are available for each services" 18 | article: service-discovery.html 19 | 20 | - name: "Routing Configuration" 21 | icon: "sitemap" 22 | description: "[RDS](https://www.envoyproxy.io/docs/envoy/latest/configuration/http_conn_man/rds) lets you move routing configuration out of static configs and into a type-safe API, making typos and merge conflicts a thing of the past." 23 | article: routing-configuration.html 24 | 25 | - name: "Securing with SSL" 26 | icon: "lock" 27 | description: "Configure Envoy to terminate [SSL or TLS](https://www.envoyproxy.io/docs/envoy/v1.6.0/intro/arch_overview/ssl.html) when used as a public-facing proxy." 28 | article: ssl.html 29 | -------------------------------------------------------------------------------- /_data/getting-started.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Turbine Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - name: "On Your Laptop" 16 | icon: "laptop" 17 | description: "Getting Envoy configured locally is a great way to start learning about all of its parts. A minimal setup is fast, especially with a few default configurations." 18 | article: on-your-laptop.html 19 | 20 | - name: "Routing Basics" 21 | icon: "share" 22 | description: "Send your first request through the proxy to a service running on your laptop, and learn how to connect more services to Envoy." 23 | article: routing-basics.html 24 | 25 | - name: "Getting Help" 26 | icon: "question-circle" 27 | description: "Stuck? Found an edge-case issue? Here's where to go to get answers, and the information you’ll need to dig into any issue." 28 | article: getting-help.html 29 | -------------------------------------------------------------------------------- /_data/observability.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Turbine Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - name: "Log Parsing" 16 | icon: "bolt" 17 | description: "Envoy’s logs contain a lot of data that you can’t get from the auto-generated summaries. Decide what’s useful to you, configure [LDS](https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/lds) to emit these logs, parse them and forward them to an appropriate consumer." 18 | 19 | - name: "Metrics Aggregation" 20 | icon: "database" 21 | description: "Information on one Envoy is great, but information about your entire environment is better. Use the Envoy primitives to aggregate information about clusters/services, domains/routes, and servers/nodes." 22 | 23 | - name: "Change Logging" 24 | icon: "eye" 25 | description: "Unlike traditional serving layers, Envoy’s behavior can change without human intervention. Use the admin interface to inspect the current state of an Envoy instance, including backend health and other runtime metrics." 26 | -------------------------------------------------------------------------------- /_data/resilience.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Turbine Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - name: "Circuit Breaking" 16 | icon: "unlink" 17 | description: "Fail quickly and apply back pressure downstream for your connections. Start with 1,000% of your max expected load on most services." 18 | article: circuit-breaking.html 19 | 20 | - name: "Automatic Retries" 21 | icon: "redo" 22 | description: "Finely-tune retries to ensure that hiccups don't lead to downtime, without making things worse when backends are unhealthy." 23 | article: automatic-retries.html 24 | 25 | - name: "Health Checks" 26 | icon: "heart" 27 | description: "Identify unhealthy hosts within services and automatically remove them from the load balancing rotation until they become healthy again." 28 | article: health-check.html 29 | 30 | # Nulls to pad out out the column 31 | - blank: true 32 | 33 | - name: "Backpressure" 34 | icon: "hand-paper" 35 | description: "A comprehensive list of ways Envoy can send an unsuccessful response to the downstream client, based on a failure within Envoy or from upstream." 36 | article: backpressure.html 37 | -------------------------------------------------------------------------------- /_includes/article-hero.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 | 19 |
20 |
21 |
22 |
{{ page.title }}
23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /_includes/article-link.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | {% if service.name %} 18 |
19 | {% if service.article %} 20 | 21 | 22 | 23 | 24 | 25 | 26 |

27 | {{ service.name }} 28 |

29 | {% else %} 30 | 31 | 32 | 33 | 34 |

{{ service.name }}

35 | {% endif %} 36 |
37 | {{ service.description | markdownify }} 38 |
39 |
40 | {% else %} 41 |
42 | {% endif %} 43 | -------------------------------------------------------------------------------- /_includes/building-on.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 |
19 |
20 |
21 |
22 |

Building On Envoy

23 |

Tools are good. Solutions are better. The best companies use Envoy’s capabilities to democratize capabilities that normally require arcane knowledge and deep expertise. Be careful: once you’ve tried some of these workflows, you may not be able to go back. 24 |

25 |
26 |
27 |
28 | {% for service in site.data.building-on %} 29 | {% include article-link.html %} 30 | {% endfor %} 31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /_includes/deployment-models.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 |
19 |
20 |
21 |
22 |

Deployment Models

23 |

Envoy’s small 24 | footprint allows for a variety of models. Most companies end up 25 | running multiple models to support: 26 |

27 |
28 |
29 |
30 | {% for service in site.data.deployment-models %} 31 | {% include article-link.html %} 32 | {% endfor %} 33 |
34 |
35 |
36 | -------------------------------------------------------------------------------- /_includes/dynamic-configuration.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 |
19 |
20 |
21 |
22 |

Dynamic Configuration

23 |

24 | Envoy's powerful configuration model is miles ahead of other 25 | open-source serving layers. Envoy uses pluggable, dynamic APIs 26 | instead of static files, allowing changes to your environment 27 | to be applied instantly, with no service interruption. 28 | 29 | You can get Envoy set up on your laptop with a bootstrap 30 | config, then extend it as you need more functionality. As your 31 | Envoy fleet grows, centralize configuration in a control plane 32 | that implements Envoy's xDS APIs. 33 |

34 |
35 |
36 |
37 | {% for service in site.data.dynamic-configuration %} 38 | {% include article-link.html %} 39 | {% endfor %} 40 |
41 |
42 |
43 | -------------------------------------------------------------------------------- /_includes/footer.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 | 19 | 71 | -------------------------------------------------------------------------------- /_includes/getting-started.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 |
19 |
20 |
21 |
22 |

Getting Started

23 |

You can get Envoy set up on your laptop with a bootstrap config, then extend it as you need more functionality. Start seeing the benefits, and learn how to talk to the community when you get stuck. 24 |

25 |
26 |
27 |
28 | {% for service in site.data.getting-started %} 29 | {% include article-link.html %} 30 | {% endfor %} 31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /_includes/head.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 33 | 37 | 41 | 42 | {% if page.title %}{{ page.title | escape }}{% else %}{{ site.title | escape }}{% endif %} 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /_includes/hero.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 | 19 |
20 |
21 |
22 |
Practical Envoy
23 |
24 | Distributed systems are hard, but upgrading your networking with Envoy doesn’t have to be. Read on for common best practices of successful, production-grade Envoy deployments, drawn from the experience of engineers from the largest cloud-native applications on the planet. 25 |
26 |
27 |
28 | 29 |
30 | -------------------------------------------------------------------------------- /_includes/mailchimp.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 |
19 |
20 |
21 |

22 |

Get tips, tricks, news, and articles in your inbox weekly. No spam, we promise.

23 | 24 |
25 | 26 |
27 | 28 | 29 |
30 |
31 |
32 |
33 | 34 | -------------------------------------------------------------------------------- /_includes/nav.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 | 58 | -------------------------------------------------------------------------------- /_includes/observability.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 |
19 |
20 |
21 |
22 |

Observability

23 |

Once Envoy is emitting the right data, what do you do with it?

24 |
25 |
26 |
27 | {% for service in site.data.observability %} 28 | {% include article-link.html %} 29 | {% endfor %} 30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /_includes/resilience.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | {% endcomment %} 16 | 17 | 18 |
19 |
20 |
21 |
22 |

Resilience

23 |

No two distributed 24 | systems are alike, and this only gets more true as systems get 25 | larger. Here’s how teams have approached the particularly thorny 26 | problem of managing dozens or hundreds of services at scale. Use 27 | their experience to solve your issues quickly. 28 |

29 |
30 |
31 |
32 | {% for service in site.data.resilience %} 33 | {% include article-link.html %} 34 | {% endfor %} 35 |
36 |
37 |
38 | -------------------------------------------------------------------------------- /_layouts/article.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | {% comment %} 5 | Copyright 2018 Turbine Labs, Inc. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | {% endcomment %} 19 | 20 | {% include article-hero.html %} 21 | 22 |
23 |
24 |
25 | {{ content }} 26 |
27 |
28 |
29 | {% include mailchimp.html %} 30 | -------------------------------------------------------------------------------- /_layouts/compress.html: -------------------------------------------------------------------------------- 1 | --- 2 | # Jekyll layout that compresses HTML 3 | # v3.0.4 4 | # http://jch.penibelst.de/ 5 | # © 2014–2015 Anatol Broder 6 | # MIT License 7 | --- 8 | 9 | {% capture _LINE_FEED %} 10 | {% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "" %}{% endif %}{% unless _pre_before contains "" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " ;; ;" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %}
Step Bytes
raw {{ content | size }}{% if _profile_endings %}
endings {{ _profile_endings }}{% endif %}{% if _profile_startings %}
startings {{ _profile_startings }}{% endif %}{% if _profile_comments %}
comments {{ _profile_comments }}{% endif %}{% if _profile_collapse %}
collapse {{ _profile_collapse }}{% endif %}{% if _profile_clippings %}
clippings {{ _profile_clippings }}{% endif %}
{% endif %}{% endif %} 11 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: compress 3 | --- 4 | 5 | 6 | 7 | {% include head.html %} 8 | 9 | 10 | {% include nav.html %} 11 | 12 | {{ content }} 13 | 14 | {% include footer.html %} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /_layouts/main.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | {% comment %} 5 | Copyright 2018 Turbine Labs, Inc. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | {% endcomment %} 19 | 20 | {% include hero.html %} 21 | {% include getting-started.html %} 22 | {% include dynamic-configuration.html %} 23 | {% include observability.html %} 24 | {% include deployment-models.html %} 25 | {% include resilience.html %} 26 | {% include building-on.html %} 27 | {% include mailchimp.html %} 28 | {% include portfolio-modals.html %} 29 | -------------------------------------------------------------------------------- /_sass/_mixins.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Mixins 18 | 19 | // Bootstrap Button Variant 20 | 21 | @mixin button-variant($color, $background, $border) { 22 | color: $color; 23 | background-color: $background; 24 | border-color: $border; 25 | 26 | &:focus, 27 | &.focus { 28 | color: $color; 29 | background-color: darken($background, 10%); 30 | border-color: darken($border, 25%); 31 | } 32 | &:hover { 33 | color: $color; 34 | background-color: darken($background, 10%); 35 | border-color: darken($border, 12%); 36 | } 37 | &:active, 38 | &.active, 39 | .open > &.dropdown-toggle { 40 | color: $color; 41 | background-color: darken($background, 10%); 42 | border-color: darken($border, 12%); 43 | 44 | &:hover, 45 | &:focus, 46 | &.focus { 47 | color: $color; 48 | background-color: darken($background, 17%); 49 | border-color: darken($border, 25%); 50 | } 51 | } 52 | &:active, 53 | &.active, 54 | .open > &.dropdown-toggle { 55 | background-image: none; 56 | } 57 | &.disabled, 58 | &[disabled], 59 | fieldset[disabled] & { 60 | &:hover, 61 | &:focus, 62 | &.focus { 63 | background-color: $background; 64 | border-color: $border; 65 | } 66 | } 67 | 68 | .badge { 69 | color: $background; 70 | background-color: $color; 71 | } 72 | } 73 | 74 | // Background Cover Mixin 75 | 76 | @mixin background-cover { 77 | -webkit-background-size: cover; 78 | -moz-background-size: cover; 79 | background-size: cover; 80 | -o-background-size: cover; 81 | } 82 | 83 | // Font Mixins 84 | 85 | @mixin serif-font { 86 | font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; 87 | font-weight: 400; 88 | } 89 | 90 | @mixin script-font { 91 | font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; 92 | font-weight: 500; 93 | } 94 | 95 | @mixin body-font { 96 | font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; 97 | font-weight: 300; 98 | } 99 | 100 | @mixin heading-font { 101 | font-family: "Roboto Slab", "Helvetica Neue", Helvetica, Arial, sans-serif; 102 | font-weight: 500; 103 | } 104 | -------------------------------------------------------------------------------- /_sass/_variables.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Variables 18 | 19 | $header-height: 70px; 20 | 21 | // Gray and Brand Colors for use across theme 22 | 23 | $theme-primary: #ff8322; 24 | $theme-secondary: #fdbc00; 25 | $theme-danger: #e74c3c; 26 | 27 | $gray-base: #000 !default; 28 | $gray-darker: lighten($gray-base, 13.5%) !default; // #222 29 | $gray-dark: lighten($gray-base, 20%) !default; // #333 30 | $gray: lighten($gray-base, 33.5%) !default; // #555 31 | $gray-light: lighten($gray-base, 46.7%) !default; // #777 32 | $gray-lighter: lighten($gray-base, 93.5%) !default; // #eee 33 | -------------------------------------------------------------------------------- /_sass/learnenvoy.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | @import "variables.scss"; 18 | @import "mixins.scss"; 19 | 20 | header.article { 21 | background: linear-gradient(to right, $gray-darker, $gray-dark); 22 | .intro-text { 23 | padding-top: 100px; 24 | padding-bottom: 50px; 25 | .intro-heading { 26 | font-size: 55px; 27 | padding-top: 15px; 28 | margin-top: 15px; 29 | } 30 | } 31 | } 32 | 33 | @media (min-width: 1200px) { 34 | .container{ 35 | max-width: 970px; 36 | } 37 | } 38 | 39 | div.article { 40 | padding-top: 25px; 41 | padding-bottom: 25px; 42 | margin: auto; 43 | } 44 | 45 | header { 46 | background: linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url('../assets/img/envoy-header-bg.jpg'); 47 | background-size: cover; 48 | background-position: 50% 25%; 49 | .intro-text { 50 | padding-top: 125px; 51 | .intro-description { 52 | @include body-font; 53 | padding-top: 25px; 54 | padding-bottom: 25px; 55 | margin-bottom: 25px; 56 | font-size: 20px; 57 | font-weight: 300; 58 | max-width: 550px; 59 | margin: auto; 60 | } 61 | .intro-heading { 62 | padding-top: 25px; 63 | margin-top: 25px; 64 | } 65 | } 66 | } 67 | 68 | ul.social-buttons { 69 | li { 70 | a { 71 | &:focus { 72 | background-color: $gray-darker; 73 | } 74 | } 75 | } 76 | } 77 | 78 | footer { 79 | padding-top:0px; 80 | .incubated-by { 81 | line-height: 75px; 82 | background: linear-gradient(to right, $gray-darker, $gray-dark); 83 | background-color: black; 84 | color: white; 85 | padding-top: 15px; 86 | padding-bottom: 10px; 87 | margin-bottom: 20px; 88 | margin-top:0px; 89 | } 90 | img.footer-logo-large { 91 | height: 80px; 92 | } 93 | img.footer-logo-small { 94 | height: 50px; 95 | } 96 | div { 97 | margin-top:5px; 98 | } 99 | } 100 | 101 | button.tbn-btn-code-copy { 102 | background: none; 103 | border: none; 104 | border: solid 1px rgba(0,0,0,0); 105 | border-radius: 4px; 106 | color: #999; 107 | cursor: pointer; 108 | display: block; 109 | float: right; 110 | margin-top: 0; 111 | transition: all 0.2s; 112 | width: 30px; 113 | } 114 | 115 | button.tbn-btn-code-copy:active { 116 | background-color: $theme-secondary; 117 | outline: none; 118 | } 119 | 120 | button.tbn-btn-code-copy:hover { 121 | border-color: $theme-primary; 122 | } 123 | -------------------------------------------------------------------------------- /_sass/mailchimp.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | @import "variables.scss"; 18 | @import "mixins.scss"; 19 | 20 | #mc_embed_signup form { 21 | text-align:center; 22 | margin-top: 25px; 23 | padding:50px 0 75px 0; 24 | background-color: $gray-lighter; 25 | 26 | p { 27 | padding-bottom: 1em; 28 | } 29 | 30 | input.email { 31 | @include body-font; 32 | border: 1px solid #ABB0B2; 33 | -webkit-border-radius: 3px; 34 | -moz-border-radius: 3px; 35 | border-radius: 3px; 36 | color: #343434; 37 | background-color: #fff; 38 | box-sizing:border-box; 39 | height:32px; 40 | padding: 0px 0.4em; 41 | display: inline-block; 42 | margin: 0; 43 | width:350px; 44 | vertical-align:top; 45 | } 46 | 47 | label { 48 | @include heading-font; 49 | display:block; 50 | padding-bottom:10px; 51 | font-weight:bold; 52 | } 53 | 54 | .clear { 55 | /* positions button horizontally in line with input */ 56 | display: inline-block; 57 | } 58 | 59 | .button { 60 | font-size: 13px; 61 | border: none; 62 | -webkit-border-radius: 3px; 63 | -moz-border-radius: 3px; 64 | border-radius: 3px; 65 | letter-spacing: .03em; 66 | color: #fff; 67 | background-color: $theme-primary; 68 | box-sizing:border-box; 69 | height:32px; 70 | line-height:32px; 71 | padding:0 18px; 72 | display: inline-block; 73 | margin: 0; 74 | transition: all 0.23s ease-in-out 0s; 75 | } 76 | .button:hover { 77 | background-color:darken($theme-primary, 25%); 78 | cursor:pointer; 79 | } 80 | 81 | div#mce-responses { 82 | float:left; 83 | top:-1.4em; 84 | padding:0em .5em 0em .5em; 85 | overflow:hidden; 86 | width:90%; 87 | margin: 0 5%; 88 | clear: both; 89 | } 90 | div.response { 91 | margin:1em 0; 92 | padding:1em .5em .5em 0; 93 | font-weight:bold; 94 | float:left; 95 | top:-1.5em; 96 | z-index:1; 97 | width:80%; 98 | } 99 | #mce-error-response { 100 | display:none; 101 | } 102 | #mce-success-response { 103 | color:#529214; 104 | display:none; 105 | } 106 | label.error { 107 | display:block; 108 | float:none; 109 | width:auto; 110 | margin-left:1.05em; 111 | text-align:left; 112 | padding:.5em 0; 113 | } 114 | } 115 | 116 | .mc-field-group { 117 | /* positions input field horizontally */ 118 | display: inline-block; 119 | } 120 | 121 | @media (max-width: 768px) { 122 | #mc_embed_signup form { 123 | input.email { 124 | width:100%; 125 | margin:0; 126 | } 127 | .clear { 128 | display: block; 129 | width: 100% 130 | } 131 | .button { 132 | width:100%; 133 | margin: 10px 0 0 0; 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /_sass/site.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/envoyproxy/learnenvoy/4fae9430a36700a2032ade87599576531194ee0a/assets/.DS_Store -------------------------------------------------------------------------------- /assets/android-chrome-192x192.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:98fb7403547131fb119e3515e1775b7a3f9faae2f88026433aa5dd0bbcbe054d 3 | size 6633 4 | -------------------------------------------------------------------------------- /assets/apple-touch-icon.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:33db8ce4407c44c14491cbf6444d821b5666d45647ac4734e182b66a0396028d 3 | size 3453 4 | -------------------------------------------------------------------------------- /assets/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #9f00a7 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /assets/codeButton.js: -------------------------------------------------------------------------------- 1 | function stripPrompts(s) { 2 | // replace any leading '$' plus any whitespace (\s*) with the empty string 3 | // options: (g = global, m = multiline) 4 | return s.replace(/^\$\s*/gm, '') 5 | } 6 | 7 | const languageSelector = '.language-console, .language-json, .language-yaml' 8 | 9 | function handleClick(e) { 10 | e.preventDefault() 11 | e.stopPropagation() 12 | // get the button's parent's child language-console code block 13 | var code = $(e.delegateTarget).parent().find(languageSelector) 14 | // process the text. TODO #3140: be more robust about when not to strip 15 | // leading $. OK for now, since leading $ are illegal in both yaml and json. 16 | var copyString = stripPrompts(code.text()) 17 | // get the global copy input field and set its value to the processed string 18 | var input = $('.tbn-code-copy-input').val(copyString) 19 | // select the input field 20 | input.select() 21 | // tell the browser to copy the currently selected text 22 | try { 23 | document.execCommand('copy') 24 | } catch (e) {} 25 | // un-focus the input element so Firefox doesn't try to scroll to it. 26 | input.blur() 27 | } 28 | 29 | $(function() { 30 | // create the hidden input 31 | $('body').append('') 32 | // actually hide it by moving it off screen 33 | $('.tbn-code-copy-input').css('position', 'absolute').css('left', '-9999px') 34 | // get all the 'console' code blocks and add a copy button immediately after them 35 | // NOTE: Firefox choked on parsing prettier's formatting for the next block, so... 36 | // prettier-ignore 37 | $(languageSelector) 38 | .parent() 39 | .before('') 40 | // add handlers to all the new copy buttons 41 | var buttons = $('.tbn-btn-code-copy').on('click', handleClick) 42 | }) 43 | -------------------------------------------------------------------------------- /assets/copy_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/favicon-16x16.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f370f46e5c6907430ad9d0edceb173fd1d2520ccc756dc710e9bdb92aacd5d61 3 | size 643 4 | -------------------------------------------------------------------------------- /assets/favicon-32x32.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:06183bb12eea8994d7b4f55801e24c7e5e40747a208da32776f663957f01d437 3 | size 1000 4 | -------------------------------------------------------------------------------- /assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/envoyproxy/learnenvoy/4fae9430a36700a2032ade87599576531194ee0a/assets/favicon.ico -------------------------------------------------------------------------------- /assets/img/envoy-article-header-bg.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dc4f54d21560b541c5cb92f88a0d70a431adb247086c8a456650236e4e3ff6bb 3 | size 175226 4 | -------------------------------------------------------------------------------- /assets/img/envoy-header-bg.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ce101733e09cd0d6213b26e2f3d2813fafe393d9eee803f54bfa2752e0382f39 3 | size 298979 4 | -------------------------------------------------------------------------------- /assets/img/envoy-horizontal-color.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0faf760d68fc3860cfd8415d5563229097481ec15d81bf94d06cc1d42017070c 3 | size 49908 4 | -------------------------------------------------------------------------------- /assets/img/logo-horiz-3c.svg: -------------------------------------------------------------------------------- 1 | Turbine Labs, Inc. 2 | -------------------------------------------------------------------------------- /assets/main.scss: -------------------------------------------------------------------------------- 1 | --- 2 | # Only the main Sass file needs front matter (the dashes are enough) 3 | --- 4 | @charset "utf-8"; 5 | 6 | // Our variables 7 | 8 | 9 | 10 | // Width of the content area 11 | 12 | 13 | 14 | 15 | // Import partials 16 | @import "agency"; 17 | @import "site"; 18 | @import "learnenvoy"; 19 | @import "mailchimp"; 20 | -------------------------------------------------------------------------------- /assets/mstile-150x150.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:71673d9cc59a7536c6ba0ef81306229d8ea6b47c059f05b275aa5c521d01f11c 3 | size 2484 4 | -------------------------------------------------------------------------------- /assets/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LearnEnvoy", 3 | "short_name": "LearnEnvoy", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | } 10 | ], 11 | "theme_color": "#ffffff", 12 | "background_color": "#ffffff", 13 | "display": "standalone" 14 | } 15 | -------------------------------------------------------------------------------- /assets/vendor.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Turbine Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/ruby:2.5-node 6 | steps: 7 | - checkout 8 | 9 | - run: env | sort 10 | 11 | - run: bundle -v 12 | 13 | - restore_cache: 14 | keys: 15 | - learnenvoy-bundler-cache-v1-{{ checksum "Gemfile.lock" }} 16 | - learnenvoy-bundler-cache-v1- 17 | 18 | - run: make test 19 | 20 | - save_cache: 21 | key: learnenvoy-bundler-cache-v1-{{ checksum "Gemfile.lock" }} 22 | paths: 23 | - vendor/bundler 24 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: main 3 | --- 4 | {% comment %} 5 | Copyright 2018 Turbine Labs, Inc. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | {% endcomment %} 19 | 20 |
21 | 22 |

Posts

23 | 24 |
    25 | {% for post in site.posts %} 26 |
  • 27 | 28 | {{ post.title }} 29 |
  • 30 | {% endfor %} 31 |
32 | 33 |

subscribe via RSS

34 | 35 |
36 | --------------------------------------------------------------------------------