istio.io/archive/v1.0/blog/2018/egress-tcp/index.html

175 lines
49 KiB
HTML

<!doctype html><html lang=en itemscope itemtype=https://schema.org/WebPage><head><meta charset=utf-8><meta http-equiv=x-ua-compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name=theme-color content="#466BB0"><meta name=title content="Consuming External TCP Services"><meta name=description content="Describes a simple scenario based on Istio's Bookinfo example."><meta name=author content="Vadim Eisenberg"><meta name=keywords content="microservices,services,mesh,traffic-management,egress,tcp"><meta property="og:title" content="Consuming External TCP Services"><meta property="og:type" content="website"><meta property="og:description" content="Describes a simple scenario based on Istio's Bookinfo example."><meta property="og:url" content="/v1.0/blog/2018/egress-tcp/"><meta property="og:image" content="/v1.0/img/istio-logo-blue-background.svg"><meta property="og:image:alt" content="Istio Logo"><meta property="og:image:width" content="112"><meta property="og:image:height" content="150"><meta property="og:site_name" content="Istio"><meta name=twitter:card content="summary"><meta name=twitter:site content="@IstioMesh"><title>Istioldie 1.0 / Consuming External TCP Services</title><script async src="https://www.googletagmanager.com/gtag/js?id=UA-98480406-2"></script><script>window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}
gtag('js',new Date());gtag('config','UA-98480406-2');</script><script>var branchName="release-1.0";var docTitle="Consuming External TCP Services";</script><link rel=alternate type=application/rss+xml title="Istio Blog" href=/v1.0/feed.xml><link rel="shortcut icon" href=/v1.0/favicons/favicon.ico><link rel=apple-touch-icon href=/v1.0/favicons/apple-touch-icon-180x180.png sizes=180x180><link rel=icon type=image/png href=/v1.0/favicons/favicon-16x16.png sizes=16x16><link rel=icon type=image/png href=/v1.0/favicons/favicon-32x32.png sizes=32x32><link rel=icon type=image/png href=/v1.0/favicons/android-36x36.png sizes=36x36><link rel=icon type=image/png href=/v1.0/favicons/android-48x48.png sizes=48x48><link rel=icon type=image/png href=/v1.0/favicons/android-72x72.png sizes=72x72><link rel=icon type=image/png href=/v1.0/favicons/android-96x196.png sizes=96x196><link rel=icon type=image/png href=/v1.0/favicons/android-144x144.png sizes=144x144><link rel=icon type=image/png href=/v1.0/favicons/android-192x192.png sizes=192x192><link rel=manifest href=/v1.0/manifest.json><meta name=apple-mobile-web-app-title content="Istio"><meta name=application-name content="Istio"><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Chivo:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic"><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Work Sans:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic"><link rel=stylesheet href=https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css integrity=sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm crossorigin=anonymous><link rel=stylesheet href=https://use.fontawesome.com/releases/v5.0.6/css/all.css><link rel=stylesheet href=/v1.0/css/light_theme_archive.css title=light><link rel="alternate stylesheet" href=/v1.0/css/dark_theme_archive.css title=dark><script src=/v1.0/js/styleSwitcher.min.js></script></head><body class=language-unknown><header><nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark justify-content-between"><a class=navbar-brand href=/v1.0/><span class=logo><svg viewBox="0 0 300 300"><circle cx="150" cy="150" r="150" stroke-width="2" /><polygon points="65,240 225,240 125,270"/><polygon points="65,230 125,220 125,110"/><polygon points="135,220 225,230 135,30"/></svg></span><span class=brand-name>Istioldie 1.0</span></a>
<button class=navbar-toggler type=button data-toggle=collapse data-target=#navbarCollapse aria-controls=navbarCollapse aria-expanded=false aria-label="Toggle navigation">
<span class=navbar-toggler-icon></span></button><div class="collapse navbar-collapse justify-content-end" id=navbarCollapse><ul id=navbar-links class="navbar-nav active"><li class=nav-item><a class=nav-link title="Learn how to deploy, use, and operate Istio." href=/v1.0/docs/>Docs</a></li><li class=nav-item><a class="nav-link active" title="Posts about using Istio." href=/v1.0/blog/2019/announcing-1.0.6/>Blog</a></li><li class=nav-item><a class=nav-link title="A bunch of resources to help you deploy, configure and use Istio." href=/v1.0/help/>Help</a></li><li class=nav-item><a class=nav-link title="Get a bit more in-depth info about the Istio project." href=/v1.0/about/>About</a></li><li class="nav-item dropdown" id=gearDropdown style=white-space:nowrap><a title="Options and Settings" href class=nav-link data-toggle=dropdown aria-label=Tools aria-haspopup=true aria-expanded=false><i style=width:1em class="fa fa-lg fa-cog"></i></a><div class="dropdown-menu dropdown-menu-right" aria-labelledby=gearDropdown><a class=dropdown-item id=light-theme-item href onclick="setActiveStyleSheet('light');return false;">Light Theme</a>
<a class=dropdown-item id=dark-theme-item href onclick="setActiveStyleSheet('dark');return false;">Dark Theme</a><div class=dropdown-divider></div><h6 class=dropdown-header>Other versions of this site</h6><a href=https://istio.io class=dropdown-item>Current Release</a>
<a href=https://preliminary.istio.io class=dropdown-item>Next Release</a>
<a href=https://archive.istio.io class=dropdown-item>Older Releases</a></div></li><li class=nav-item><a id=search_show class=nav-link href title="Search istio.io" aria-label=Search><i style=width:1em class="fa fa-lg fa-search"></i></a></li></ul><form name=cse id=search_form class="form-inline mr-sm-2" role=search><input type=hidden name=cx value=013699703217164175118:iwwf17ikgf4>
<input type=hidden name=ie value=utf-8>
<input type=hidden name=hl value=en>
<input type=hidden id=search_page_url value=/v1.0/search.html>
<input id=search_textbox class=form-control name=q type=text aria-label="Search this site">
<button id=search_close type=reset aria-label="Cancel Search"><i class="far fa-lg fa-times-circle"></i></button></form></div></nav></header><div class=blog><div class=container-fluid><div class="row row-offcanvas"><div class="col-0 col-md-3 col-xl-2 sidebar-offcanvas"><nav class="sidebar d-print-none"><div class=spacer></div><div class=directory role=tablist><div class=card><div class=card-header role=tab id=header0><a data-toggle=collapse href=#collapse0 title="Blog posts for 2019." role=button aria-controls=collapse0><div><img src=/v1.0/img/blog.svg alt=Icon class=page_icon>
2019 Posts</div></a></div><div id=collapse0 class=collapse data-parent=#sidebar role=tabpanel aria-labelledby=header0><div class=card-body><ul class=tree><li><a title="Istio 1.0.6 patch release." href=/v1.0/blog/2019/announcing-1.0.6/>Announcing Istio 1.0.6</a></li><li><a title="Addressing application startup ordering and startup latency using AppSwitch." href=/v1.0/blog/2019/appswitch/>Sidestepping Dependency Ordering with AppSwitch</a></li><li><a title="Describes how to deploy a custom ingress gateway using cert-manager manually." href=/v1.0/blog/2019/custom-ingress-gateway/>Deploy a custom ingress gateway using cert-manager</a></li><li><a title="Istio has a new discussion board." href=/v1.0/blog/2019/announcing-discuss.istio.io/>Announcing discuss.istio.io</a></li></ul></div></div></div><div class=card><div class=card-header role=tab id=header1><a data-toggle=collapse href=#collapse1 title="Blog posts for 2018." role=button aria-controls=collapse1><div><img src=/v1.0/img/blog.svg alt=Icon class=page_icon>
2018 Posts</div></a></div><div id=collapse1 class="collapse show" data-parent=#sidebar role=tabpanel aria-labelledby=header1><div class=card-body><ul class=tree><li><a title="Istio 1.0.5 patch release." href=/v1.0/blog/2018/announcing-1.0.5/>Announcing Istio 1.0.5</a></li><li><a title="How to use Istio for traffic management without deploying sidecar proxies." href=/v1.0/blog/2018/incremental-traffic-management/>Incremental Istio Part 1, Traffic Management</a></li><li><a title="Istio 1.0.4 patch release." href=/v1.0/blog/2018/announcing-1.0.4/>Announcing Istio 1.0.4</a></li><li><a title="Istio 1.0.3 patch release." href=/v1.0/blog/2018/announcing-1.0.3/>Announcing Istio 1.0.3</a></li><li><a title="Istio 1.0.2 patch release." href=/v1.0/blog/2018/announcing-1.0.2/>Announcing Istio 1.0.2</a></li><li><a title="Istio 1.0.1 patch release." href=/v1.0/blog/2018/announcing-1.0.1/>Announcing Istio 1.0.1</a></li><li><a title="Istio hosting an all day Twitch stream to celebrate the 1.0 release." href=/v1.0/blog/2018/istio-twitch-stream/>All Day Istio Twitch Stream</a></li><li><a title="How HP is building its next-generation footwear personalization platform on Istio." href=/v1.0/blog/2018/hp/>Istio a Game Changer for HP's FitStation Platform</a></li><li><a title="Istio is ready for production use with its 1.0 release." href=/v1.0/blog/2018/announcing-1.0/>Announcing Istio 1.0</a></li><li><a title="Automatic application onboarding and latency optimizations using AppSwitch." href=/v1.0/blog/2018/delayering-istio/delayering-istio/>Delayering Istio with AppSwitch</a></li><li><a title="Describe Istio's authorization feature and how to use it in various use cases." href=/v1.0/blog/2018/istio-authorization/>Micro-Segmentation with Istio Authorization</a></li><li><a title="How to export Istio Access Logs to different sinks like BigQuery, GCS, Pub/Sub through Stackdriver." href=/v1.0/blog/2018/export-logs-through-stackdriver/>Exporting Logs to BigQuery, GCS, Pub/Sub through Stackdriver</a></li><li><a title="Introduction, motivation and design principles for the Istio v1alpha3 routing API." href=/v1.0/blog/2018/v1alpha3-routing/>Introducing the Istio v1alpha3 routing API</a></li><li><a title="Describes how to configure Istio ingress with a network load balancer on AWS." href=/v1.0/blog/2018/aws-nlb/>Configuring Istio Ingress with AWS NLB</a></li><li><a title="Using Kubernetes namespaces and RBAC to create an Istio soft multi-tenancy environment." href=/v1.0/blog/2018/soft-multitenancy/>Istio Soft Multi-tenancy Support</a></li><li><a title="An introduction to safer, lower-risk deployments and release to production." href=/v1.0/blog/2018/traffic-mirroring/>Traffic Mirroring with Istio for Testing in Production</a></li><li><span class=current title="Describes a simple scenario based on Istio's Bookinfo example.">Consuming External TCP Services</span></li><li><a title="Describes a simple scenario based on Istio's Bookinfo example." href=/v1.0/blog/2018/egress-https/>Consuming External Web Services</a></li></ul></div></div></div><div class=card><div class=card-header role=tab id=header2><a data-toggle=collapse href=#collapse2 title="Blog posts for 2017." role=button aria-controls=collapse2><div><img src=/v1.0/img/blog.svg alt=Icon class=page_icon>
2017 Posts</div></a></div><div id=collapse2 class=collapse data-parent=#sidebar role=tabpanel aria-labelledby=header2><div class=card-body><ul class=tree><li><a title="Improving availability and reducing latency." href=/v1.0/blog/2017/mixer-spof-myth/>Mixer and the SPOF Myth</a></li><li><a title="Provides an overview of Mixer's plug-in architecture." href=/v1.0/blog/2017/adapter-model/>Mixer Adapter Model</a></li><li><a title="Istio 0.2 announcement." href=/v1.0/blog/2017/0.2-announcement/>Announcing Istio 0.2</a></li><li><a title="How Kubernetes Network Policy relates to Istio policy." href=/v1.0/blog/2017/0.1-using-network-policy/>Using Network Policy with Istio</a></li><li><a title="Using Istio to create autoscaled canary deployments." href=/v1.0/blog/2017/0.1-canary/>Canary Deployments using Istio</a></li><li><a title="Istio Auth 0.1 announcement." href=/v1.0/blog/2017/0.1-auth/>Using Istio to Improve End-to-End Security</a></li><li><a title="Istio 0.1 announcement." href=/v1.0/blog/2017/0.1-announcement/>Introducing Istio</a></li></ul></div></div></div></div></nav></div><div class="col-12 col-md-9 col-xl-8"><p class=d-md-none><label class=sidebar-toggler data-toggle=offcanvas><i class="fa fa-sign-out-alt"></i></label></p><main aria-labelledby=title><div class=pagenav><p><a href=/v1.0/blog/2018/ title="Blog posts for 2018."><i style=transform:scaleX(-1) class="fa fa-level-up-alt"></i>&nbsp;2018 Posts</a></p></div><h1 id=title>Consuming External TCP Services</h1><p class=subtitle>Mesh-external Service Entries for TCP traffic</p><p class=byline>By <span class=attribution>Vadim Eisenberg</span>
/
<span class=publish_date>February 6, 2018</span></p><nav class="toc-inlined d-xl-none d-print-none"><hr><div class=directory role=directory><nav id=InlinedTableOfContents><ul><li><a href=#bookinfo-sample-application-with-external-ratings-database>Bookinfo sample application with external ratings database</a></li><ul><li><a href=#setting-up-the-database-for-ratings-data>Setting up the database for ratings data</a></li><li><a href=#initial-setting-of-bookinfo-application>Initial setting of Bookinfo application</a></li><li><a href=#use-the-database-for-ratings-data-in-bookinfo-application>Use the database for ratings data in Bookinfo application</a></li><li><a href=#access-the-webpage>Access the webpage</a></li><li><a href=#mesh-external-service-entry-for-an-external-mysql-instance>Mesh-external service entry for an external MySQL instance</a></li></ul><li><a href=#motivation-for-egress-tcp-traffic-control>Motivation for egress TCP traffic control</a></li><li><a href=#service-entries-for-tcp-traffic>Service entries for TCP traffic</a></li><li><a href=#relation-to-mesh-expansion>Relation to mesh expansion</a></li><li><a href=#cleanup>Cleanup</a></li><li><a href=#conclusion>Conclusion</a></li><li><a href=#see-also>See also</a></li></ul></nav></div><hr></nav><blockquote><p>This blog post was updated on July 23, 2018 to use the new
<a href=/v1.0/blog/2018/v1alpha3-routing/>v1alpha3 traffic management API</a>. If you need to use the old version, follow the docs
<a href=https://archive.istio.io/v0.7/blog/2018/egress-tcp.html>here</a>.</p></blockquote><p>In my previous blog post, <a href=/v1.0/blog/2018/egress-https/>Consuming External Web Services</a>, I described how external services
can be consumed by in-mesh Istio applications via HTTPS. In this post, I demonstrate consuming external services
over TCP. You will use the <a href=/v1.0/docs/examples/bookinfo/>Istio Bookinfo sample application</a>, the version in which the book
ratings data is persisted in a MySQL database. You deploy this database outside the cluster and configure the
<em>ratings</em> microservice to use it. You define a
<a href=/v1.0/docs/reference/config/istio.networking.v1alpha3/#ServiceEntry>Service Entry</a> to allow the in-mesh applications to
access the external database.</p><h2 id=bookinfo-sample-application-with-external-ratings-database>Bookinfo sample application with external ratings database</h2><p>First, you set up a MySQL database instance to hold book ratings data outside of your Kubernetes cluster. Then you
modify the <a href=/v1.0/docs/examples/bookinfo/>Bookinfo sample application</a> to use your database.</p><h3 id=setting-up-the-database-for-ratings-data>Setting up the database for ratings data</h3><p>For this task you set up an instance of <a href=https://www.mysql.com>MySQL</a>. You can use any MySQL instance; I used
<a href=https://www.ibm.com/cloud/compose/mysql>Compose for MySQL</a>. I used <code>mysqlsh</code>
(<a href=https://dev.mysql.com/doc/mysql-shell/en/>MySQL Shell</a>) as a MySQL client to feed the ratings data.</p><ol><li><p>Set the <code>MYSQL_DB_HOST</code> and <code>MYSQL_DB_PORT</code> environment variables:</p><pre><code class=language-command>$ export MYSQL_DB_HOST=&lt;your MySQL database host&gt;
$ export MYSQL_DB_PORT=&lt;your MySQL database port&gt;</code></pre><p>In case of a local MySQL database with the default port, the values are <code>localhost</code> and <code>3306</code>, respectively.</p></li><li><p>To initialize the database, run the following command entering the password when prompted. The command is
performed with the credentials of the <code>admin</code> user, created by default by
<a href=https://www.ibm.com/cloud/compose/mysql>Compose for MySQL</a>.</p><pre><code class=language-command>$ curl -s https://raw.githubusercontent.com/istio/istio/release-1.0/samples/bookinfo/src/mysql/mysqldb-init.sql | mysqlsh --sql --ssl-mode=REQUIRED -u admin -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT</code></pre><p><em><strong>OR</strong></em></p><p>When using the <code>mysql</code> client and a local MySQL database, run:</p><pre><code class=language-command>$ curl -s https://raw.githubusercontent.com/istio/istio/release-1.0/samples/bookinfo/src/mysql/mysqldb-init.sql | mysql -u root -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT</code></pre></li><li><p>Create a user with the name <code>bookinfo</code> and grant it <em>SELECT</em> privilege on the <code>test.ratings</code> table:</p><pre><code class=language-command>$ mysqlsh --sql --ssl-mode=REQUIRED -u admin -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;CREATE USER &#39;bookinfo&#39; IDENTIFIED BY &#39;&lt;password you choose&gt;&#39;; GRANT SELECT ON test.ratings to &#39;bookinfo&#39;;&#34;</code></pre><p><em><strong>OR</strong></em></p><p>For <code>mysql</code> and the local database, the command is:</p><pre><code class=language-command>$ mysql -u root -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;CREATE USER &#39;bookinfo&#39; IDENTIFIED BY &#39;&lt;password you choose&gt;&#39;; GRANT SELECT ON test.ratings to &#39;bookinfo&#39;;&#34;</code></pre><p>Here you apply the <a href=https://en.wikipedia.org/wiki/Principle_of_least_privilege>principle of least privilege</a>. This
means that you do not use your <code>admin</code> user in the Bookinfo application. Instead, you create a special user for the
Bookinfo application , <code>bookinfo</code>, with minimal privileges. In this case, the <em>bookinfo</em> user only has the <code>SELECT</code>
privilege on a single table.</p><p>After running the command to create the user, you may want to clean your bash history by checking the number of the last
command and running <code>history -d &lt;the number of the command that created the user></code>. You don't want the password of the
new user to be stored in the bash history. If you're using <code>mysql</code>, remove the last command from
<code>~/.mysql_history</code> file as well. Read more about password protection of the newly created user in <a href=https://dev.mysql.com/doc/refman/5.5/en/create-user.html>MySQL documentation</a>.</p></li><li><p>Inspect the created ratings to see that everything worked as expected:</p><pre><code class=language-command>$ mysqlsh --sql --ssl-mode=REQUIRED -u bookinfo -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;select * from test.ratings;&#34;
Enter password:
&#43;----------&#43;--------&#43;
| ReviewID | Rating |
&#43;----------&#43;--------&#43;
| 1 | 5 |
| 2 | 4 |
&#43;----------&#43;--------&#43;</code></pre><p><em><strong>OR</strong></em></p><p>For <code>mysql</code> and the local database:</p><pre><code class=language-command>$ mysql -u bookinfo -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;select * from test.ratings;&#34;
Enter password:
&#43;----------&#43;--------&#43;
| ReviewID | Rating |
&#43;----------&#43;--------&#43;
| 1 | 5 |
| 2 | 4 |
&#43;----------&#43;--------&#43;</code></pre></li><li><p>Set the ratings temporarily to <code>1</code> to provide a visual clue when our database is used by the Bookinfo <em>ratings</em>
service:</p><pre><code class=language-command>$ mysqlsh --sql --ssl-mode=REQUIRED -u admin -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;update test.ratings set rating=1; select * from test.ratings;&#34;
Enter password:
Rows matched: 2 Changed: 2 Warnings: 0
&#43;----------&#43;--------&#43;
| ReviewID | Rating |
&#43;----------&#43;--------&#43;
| 1 | 1 |
| 2 | 1 |
&#43;----------&#43;--------&#43;</code></pre><p><em><strong>OR</strong></em></p><p>For <code>mysql</code> and the local database:</p><pre><code class=language-command>$ mysql -u root -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;update test.ratings set rating=1; select * from test.ratings;&#34;
Enter password:
&#43;----------&#43;--------&#43;
| ReviewID | Rating |
&#43;----------&#43;--------&#43;
| 1 | 1 |
| 2 | 1 |
&#43;----------&#43;--------&#43;</code></pre><p>You used the <code>admin</code> user (and <code>root</code> for the local database) in the last command since the <code>bookinfo</code> user does not
have the <code>UPDATE</code> privilege on the <code>test.ratings</code> table.</p></li></ol><p>Now you are ready to deploy a version of the Bookinfo application that will use your database.</p><h3 id=initial-setting-of-bookinfo-application>Initial setting of Bookinfo application</h3><p>To demonstrate the scenario of using an external database, you start with a Kubernetes cluster with <a href=/v1.0/docs/setup/kubernetes/quick-start/#installation-steps>Istio installed</a>. Then you deploy the
<a href=/v1.0/docs/examples/bookinfo/>Istio Bookinfo sample application</a> and <a href=/v1.0/docs/examples/bookinfo/#apply-default-destination-rules>apply the default destination rules</a>.</p><p>This application uses the <code>ratings</code> microservice to fetch
book ratings, a number between 1 and 5. The ratings are displayed as stars for each review. There are several versions
of the <code>ratings</code> microservice. Some use <a href=https://www.mongodb.com>MongoDB</a>, others use <a href=https://www.mysql.com>MySQL</a>
as their database.</p><p>The example commands in this blog post work with Istio 0.8+, with or without
<a href=/v1.0/docs/concepts/security/#mutual-tls-authentication>mutual TLS</a> enabled.</p><p>As a reminder, here is the end-to-end architecture of the application from the
<a href=/v1.0/docs/examples/bookinfo/>Bookinfo sample application</a>.</p><figure style=width:80%><div class=wrapper-with-intrinsic-ratio style=padding-bottom:59.08%><a class=not-for-endnotes href=/v1.0/docs/examples/bookinfo/withistio.svg><img class=element-to-stretch src=/v1.0/docs/examples/bookinfo/withistio.svg alt="The original Bookinfo application" title="The original Bookinfo application"></a></div><figcaption>The original Bookinfo application</figcaption></figure><h3 id=use-the-database-for-ratings-data-in-bookinfo-application>Use the database for ratings data in Bookinfo application</h3><ol><li><p>Modify the deployment spec of a version of the <em>ratings</em> microservice that uses a MySQL database, to use your
database instance. The spec is in <a href=https://github.com/istio/istio/blob/release-1.0/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml><code>samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml</code></a>
of an Istio release archive. Edit the following lines:</p><pre><code class=language-yaml>- name: MYSQL_DB_HOST
value: mysqldb
- name: MYSQL_DB_PORT
value: &#34;3306&#34;
- name: MYSQL_DB_USER
value: root
- name: MYSQL_DB_PASSWORD
value: password</code></pre><p>Replace the values in the snippet above, specifying the database host, port, user, and password. Note that the
correct way to work with passwords in container's environment variables in Kubernetes is <a href=https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-environment-variables>to use secrets</a>. For this
example task only, you may want to write the password directly in the deployment spec. <strong>Do not do it</strong> in a real
environment! I also assume everyone realizes that <code>"password"</code> should not be used as a password&mldr;</p></li><li><p>Apply the modified spec to deploy the version of the <em>ratings</em> microservice, <em>v2-mysql</em>, that will use your
database.</p><pre><code class=language-command>$ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml@
deployment &#34;ratings-v2-mysql&#34; created</code></pre><a hidden style=display:none href=https://raw.githubusercontent.com/istio/istio/release-1.0/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml></a></li><li><p>Route all the traffic destined to the <em>reviews</em> service to its <em>v3</em> version. You do this to ensure that the
<em>reviews</em> service always calls the <em>ratings</em> service. In addition, route all the traffic destined to the <em>ratings</em>
service to <em>ratings v2-mysql</em> that uses your database.</p><p>Specify the routing for both services above by adding two
<a href=/v1.0/docs/reference/config/istio.networking.v1alpha3/#VirtualService>virtual services</a>. These virtual services are
specified in <code>samples/bookinfo/networking/virtual-service-ratings-mysql.yaml</code> of an Istio release archive.
<em><strong>Important:</strong></em> make sure you
<a href=/v1.0/docs/examples/bookinfo/#apply-default-destination-rules>applied the default destination rules</a> before running the
following command.</p><pre><code class=language-command>$ kubectl apply -f @samples/bookinfo/networking/virtual-service-ratings-mysql.yaml@</code></pre><a hidden style=display:none href=https://raw.githubusercontent.com/istio/istio/release-1.0/samples/bookinfo/networking/virtual-service-ratings-mysql.yaml></a></li></ol><p>The updated architecture appears below. Note that the blue arrows inside the mesh mark the traffic configured according
to the virtual services we added. According to the virtual services, the traffic is sent to <em>reviews v3</em> and
<em>ratings v2-mysql</em>.</p><figure style=width:80%><div class=wrapper-with-intrinsic-ratio style=padding-bottom:59.31%><a class=not-for-endnotes href=/v1.0/blog/2018/egress-tcp/./bookinfo-ratings-v2-mysql-external.svg><img class=element-to-stretch src=/v1.0/blog/2018/egress-tcp/./bookinfo-ratings-v2-mysql-external.svg alt="The Bookinfo application with ratings v2-mysql and an external MySQL database" title="The Bookinfo application with ratings v2-mysql and an external MySQL database"></a></div><figcaption>The Bookinfo application with ratings v2-mysql and an external MySQL database</figcaption></figure><p>Note that the MySQL database is outside the Istio service mesh, or more precisely outside the Kubernetes cluster. The
boundary of the service mesh is marked by a dashed line.</p><h3 id=access-the-webpage>Access the webpage</h3><p>Access the webpage of the application, after
<a href=/v1.0/docs/examples/bookinfo/#determining-the-ingress-ip-and-port>determining the ingress IP and port</a>.</p><p>You have a problem&mldr; Instead of the rating stars, the message <em>&ldquo;Ratings service is currently unavailable&rdquo;</em> is currently
displayed below each review:</p><figure style=width:80%><div class=wrapper-with-intrinsic-ratio style=padding-bottom:36.19%><a class=not-for-endnotes href=/v1.0/blog/2018/egress-tcp/./errorFetchingBookRating.png><img class=element-to-stretch src=/v1.0/blog/2018/egress-tcp/./errorFetchingBookRating.png alt="The Ratings service error messages" title="The Ratings service error messages"></a></div><figcaption>The Ratings service error messages</figcaption></figure><p>As in <a href=/v1.0/blog/2018/egress-https/>Consuming External Web Services</a>, you experience <strong>graceful service degradation</strong>,
which is good. The application did not crash due to the error in the <em>ratings</em> microservice. The webpage of the
application correctly displayed the book information, the details, and the reviews, just without the rating stars.</p><p>You have the same problem as in <a href=/v1.0/blog/2018/egress-https/>Consuming External Web Services</a>, namely all the traffic
outside the Kubernetes cluster, both TCP and HTTP, is blocked by default by the sidecar proxies. To enable such traffic
for TCP, a mesh-external service entry for TCP must be defined.</p><h3 id=mesh-external-service-entry-for-an-external-mysql-instance>Mesh-external service entry for an external MySQL instance</h3><p>TCP mesh-external service entries come to our rescue.</p><ol><li><p>Get the IP address of your MySQL database instance. As an option, you can use the
<a href=https://linux.die.net/man/1/host>host</a> command:</p><pre><code class=language-command>$ export MYSQL_DB_IP=$(host $MYSQL_DB_HOST | grep &#34; has address &#34; | cut -d&#34; &#34; -f4)</code></pre><p>For a local database, set <code>MYSQL_DB_IP</code> to contain the IP of your machine, accessible from your cluster.</p></li><li><p>Define a TCP mesh-external service entry:</p><pre><code class=language-bash>cat &lt;&lt;EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: mysql-external
spec:
hosts:
- $MYSQL_DB_HOST
addresses:
- $MYSQL_DB_IP/32
ports:
- name: tcp
number: $MYSQL_DB_PORT
protocol: tcp
location: MESH_EXTERNAL
EOF</code></pre></li><li><p>Review the service entry you just created and check that it contains the correct values:</p><pre><code class=language-command>$ kubectl get serviceentry mysql-external -o yaml
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
...</code></pre></li></ol><p>Note that for a TCP service entry, you specify <code>tcp</code> as the protocol of a port of the entry. Also note that you have to
specify the IP of the external service in the list of addresses, as a <a href=https://tools.ietf.org/html/rfc2317>CIDR</a> block
with suffix <code>32</code>.</p><p>I will talk more about TCP service entries
<a href=#service-entries-for-tcp-traffic>below</a>. For now, verify that the service entry we added fixed the problem. Access the
webpage and see if the stars are back.</p><p>It worked! Accessing the web page of the application displays the ratings without error:</p><figure style=width:80%><div class=wrapper-with-intrinsic-ratio style=padding-bottom:36.69%><a class=not-for-endnotes href=/v1.0/blog/2018/egress-tcp/./externalMySQLRatings.png><img class=element-to-stretch src=/v1.0/blog/2018/egress-tcp/./externalMySQLRatings.png alt="Book Ratings Displayed Correctly" title="Book Ratings Displayed Correctly"></a></div><figcaption>Book Ratings Displayed Correctly</figcaption></figure><p>Note that you see a one-star rating for both displayed reviews, as expected. You changed the ratings to be one star to
provide us with a visual clue that our external database is indeed being used.</p><p>As with service entries for HTTP/HTTPS, you can delete and create service entries for TCP using <code>kubectl</code>, dynamically.</p><h2 id=motivation-for-egress-tcp-traffic-control>Motivation for egress TCP traffic control</h2><p>Some in-mesh Istio applications must access external services, for example legacy systems. In many cases, the access is
not performed over HTTP or HTTPS protocols. Other TCP protocols are used, such as database-specific protocols like
<a href=https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/>MongoDB Wire Protocol</a> and <a href=https://dev.mysql.com/doc/internals/en/client-server-protocol.html>MySQL Client/Server Protocol</a> to communicate with external databases.</p><p>Next let me provide more details about the service entries for TCP traffic.</p><h2 id=service-entries-for-tcp-traffic>Service entries for TCP traffic</h2><p>The service entries for enabling TCP traffic to a specific port must specify <code>TCP</code> as the protocol of the port.
Additionally, for the <a href=https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/>MongoDB Wire Protocol</a>, the
protocol can be specified as <code>MONGO</code>, instead of <code>TCP</code>.</p><p>For the <code>addresses</code> field of the entry, a block of IPs in <a href=https://tools.ietf.org/html/rfc2317>CIDR</a>
notation must be used. Note that the <code>hosts</code> field is ignored for TCP service entries.</p><p>To enable TCP traffic to an external service by its hostname, all the IPs of the hostname must be specified. Each IP
must be specified by a CIDR block.</p><p>Note that all the IPs of an external service are not always known. To enable egress TCP traffic, only the IPs that are
used by the applications must be specified.</p><p>Also note that the IPs of an external service are not always static, for example in the case of
<a href=https://en.wikipedia.org/wiki/Content_delivery_network>CDNs</a>. Sometimes the IPs are static most of the time, but can
be changed from time to time, for example due to infrastructure changes. In these cases, if the range of the possible
IPs is known, you should specify the range by CIDR blocks. If the range of the possible IPs is not known, service
entries for TCP cannot be used and
<a href=/v1.0/docs/tasks/traffic-management/egress/#calling-external-services-directly>the external services must be called directly</a>,
bypassing the sidecar proxies.</p><h2 id=relation-to-mesh-expansion>Relation to mesh expansion</h2><p>Note that the scenario described in this post is different from the mesh expansion scenario, described in the
<a href=/v1.0/docs/examples/integrating-vms/>Integrating Virtual Machines</a> example. In that scenario, a MySQL instance runs on an
external
(outside the cluster) machine (a bare metal or a VM), integrated with the Istio service mesh. The MySQL service becomes
a first-class citizen of the mesh with all the beneficial features of Istio applicable. Among other things, the service
becomes addressable by a local cluster domain name, for example by <code>mysqldb.vm.svc.cluster.local</code>, and the communication
to it can be secured by
<a href=/v1.0/docs/concepts/security/#mutual-tls-authentication>mutual TLS authentication</a>. There is no need to create a service
entry to access this service; however, the service must be registered with Istio. To enable such integration, Istio
components (<em>Envoy proxy</em>, <em>node-agent</em>, <em>istio-agent</em>) must be installed on the machine and the Istio control plane
(<em>Pilot</em>, <em>Mixer</em>, <em>Citadel</em>) must be accessible from it. See the
<a href=/v1.0/docs/setup/kubernetes/mesh-expansion/>Istio Mesh Expansion</a> instructions for more details.</p><p>In our case, the MySQL instance can run on any machine or can be provisioned as a service by a cloud provider. There is
no requirement to integrate the machine with Istio. The Istio control plane does not have to be accessible from the
machine. In the case of MySQL as a service, the machine which MySQL runs on may be not accessible and installing on it
the required components may be impossible. In our case, the MySQL instance is addressable by its global domain name,
which could be beneficial if the consuming applications expect to use that domain name. This is especially relevant when
that expected domain name cannot be changed in the deployment configuration of the consuming applications.</p><h2 id=cleanup>Cleanup</h2><ol><li><p>Drop the <code>test</code> database and the <code>bookinfo</code> user:</p><pre><code class=language-command>$ mysqlsh --sql --ssl-mode=REQUIRED -u admin -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;drop database test; drop user bookinfo;&#34;</code></pre><p><em><strong>OR</strong></em></p><p>For <code>mysql</code> and the local database:</p><pre><code class=language-command>$ mysql -u root -p --host $MYSQL_DB_HOST --port $MYSQL_DB_PORT -e &#34;drop database test; drop user bookinfo;&#34;</code></pre></li><li><p>Remove the virtual services:</p><pre><code class=language-command>$ kubectl delete -f @samples/bookinfo/networking/virtual-service-ratings-mysql.yaml@
Deleted config: virtual-service/default/reviews
Deleted config: virtual-service/default/ratings</code></pre><a hidden style=display:none href=https://raw.githubusercontent.com/istio/istio/release-1.0/samples/bookinfo/networking/virtual-service-ratings-mysql.yaml></a></li><li><p>Undeploy <em>ratings v2-mysql</em>:</p><pre><code class=language-command>$ kubectl delete -f @samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml@
deployment &#34;ratings-v2-mysql&#34; deleted</code></pre><a hidden style=display:none href=https://raw.githubusercontent.com/istio/istio/release-1.0/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql.yaml></a></li><li><p>Delete the service entry:</p><pre><code class=language-command>$ kubectl delete serviceentry mysql-external -n default
Deleted config: serviceentry mysql-external</code></pre></li></ol><h2 id=conclusion>Conclusion</h2><p>In this blog post, I demonstrated how the microservices in an Istio service mesh can consume external services via TCP.
By default, Istio blocks all the traffic, TCP and HTTP, to the hosts outside the cluster. To enable such traffic for
TCP, TCP mesh-external service entries must be created for the service mesh.</p><h2 id=see-also>See also</h2><div class=see-also><div class=container-fluid><div class=row><div class="col-xs-12 col-sm-6 col-xl-4"><p class=link><a href=/v1.0/blog/2018/egress-https/>Consuming External Web Services</a></p><p class=desc>Describes a simple scenario based on Istio's Bookinfo example.</p></div><div class="col-xs-12 col-sm-6 col-xl-4"><p class=link><a href=/v1.0/docs/examples/advanced-egress/egress-gateway/>Configure an Egress Gateway</a></p><p class=desc>Describes how to configure Istio to direct traffic to external services through a dedicated gateway.</p></div><div class="col-xs-12 col-sm-6 col-xl-4"><p class=link><a href=/v1.0/docs/tasks/traffic-management/egress/>Control Egress Traffic</a></p><p class=desc>Describes how to configure Istio to route traffic from services in the mesh to external services.</p></div><div class="col-xs-12 col-sm-6 col-xl-4"><p class=link><a href=/v1.0/docs/examples/advanced-egress/egress-tls-origination/>TLS Origination for Egress Traffic</a></p><p class=desc>Describes how to configure Istio to perform TLS origination for traffic to external services.</p></div><div class="col-xs-12 col-sm-6 col-xl-4"><p class=link><a href=/v1.0/blog/2019/custom-ingress-gateway/>Deploy a custom ingress gateway using cert-manager</a></p><p class=desc>Describes how to deploy a custom ingress gateway using cert-manager manually.</p></div><div class="col-xs-12 col-sm-6 col-xl-4"><p class=link><a href=/v1.0/blog/2018/incremental-traffic-management/>Incremental Istio Part 1, Traffic Management</a></p><p class=desc>How to use Istio for traffic management without deploying sidecar proxies.</p></div></div></div></div></main><div class="container-fluid d-print-none"><br><div class=row><div class="col-6 pagenav"><p><a title="An introduction to safer, lower-risk deployments and release to production." href=/v1.0/blog/2018/traffic-mirroring/><i class="fa fa-long-arrow-alt-left"></i>Traffic Mirroring with Istio for Testing in Production</a></p></div><div class="col-6 pagenav" style=text-align:right><p><a title="Describes a simple scenario based on Istio's Bookinfo example." href=/v1.0/blog/2018/egress-https/>Consuming External Web Services
<i class="fa fa-long-arrow-alt-right"></i></a></p></div></div></div><div class="d-none d-print-block" aria-hidden=true><h2>Links</h2><ol id=endnotes></ol></div></div><div class="col-12 col-md-2 d-none d-xl-block d-print-none"><nav class=toc><div class=spacer></div><div id=toc class=directory role=directory><nav id=TableOfContents><ul><li><a href=#bookinfo-sample-application-with-external-ratings-database>Bookinfo sample application with external ratings database</a></li><ul><li><a href=#setting-up-the-database-for-ratings-data>Setting up the database for ratings data</a></li><li><a href=#initial-setting-of-bookinfo-application>Initial setting of Bookinfo application</a></li><li><a href=#use-the-database-for-ratings-data-in-bookinfo-application>Use the database for ratings data in Bookinfo application</a></li><li><a href=#access-the-webpage>Access the webpage</a></li><li><a href=#mesh-external-service-entry-for-an-external-mysql-instance>Mesh-external service entry for an external MySQL instance</a></li></ul><li><a href=#motivation-for-egress-tcp-traffic-control>Motivation for egress TCP traffic control</a></li><li><a href=#service-entries-for-tcp-traffic>Service entries for TCP traffic</a></li><li><a href=#relation-to-mesh-expansion>Relation to mesh expansion</a></li><li><a href=#cleanup>Cleanup</a></li><li><a href=#conclusion>Conclusion</a></li><li><a href=#see-also>See also</a></li></ul></nav></div></nav></div></div></div></div><footer class="d-print-none container-fluid"><div class=row><div class="col-5 col-lg-4" role=navigation><div class=container-fluid><div class=row><div class=icon><span>discuss</span>
<a title="Join the Istio discussion board to participate in discussions and get help troubleshooting problems" href=https://discuss.istio.io aria-label="Istio discussion board"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M225.9 32C103.3 32 0 130.5.0 252.1.0 256 .1 480 .1 480l225.8-.2c122.7.0 222.1-102.3 222.1-223.9S348.6 32 225.9 32zM224 384c-19.4.0-37.9-4.3-54.4-12.1L88.5 392l22.9-75c-9.8-18.1-15.4-38.9-15.4-61 0-70.7 57.3-128 128-128s128 57.3 128 128-57.3 128-128 128z" /></svg></a></div><div class=icon><span>slack</span>
<a title="Interactively discuss issues with the Istio community on Slack" href=https://istio.slack.com aria-label=slack><svg viewBox="0 0 31.444 31.443"><path d="M31.202 16.369c-.62-1.388-2.249-2.011-3.637-1.391l-1.325.594-3.396-7.591 1.325-.592c1.388-.622 2.01-2.25 1.389-3.637-.62-1.389-2.248-2.012-3.637-1.39l-1.324.593-.593-1.326c-.621-1.388-2.249-2.009-3.637-1.388-1.388.62-2.009 2.247-1.389 3.637l.593 1.325L7.98 8.598 7.388 7.273c-.621-1.39-2.249-2.009-3.637-1.39C2.363 6.504 1.742 8.132 2.362 9.52l.592 1.324L1.63 11.438c-1.388.621-2.01 2.247-1.389 3.636.62 1.388 2.249 2.01 3.637 1.39l1.325-.594 3.394 7.592-1.325.592c-1.388.621-2.009 2.25-1.389 3.637.621 1.389 2.249 2.011 3.637 1.391l1.324-.593.593 1.325c.621 1.389 2.249 2.01 3.637 1.389 1.387-.62 2.009-2.248 1.388-3.636l-.591-1.326 7.591-3.394.592 1.321c.621 1.391 2.248 2.013 3.637 1.392 1.388-.619 2.01-2.248 1.389-3.637l-.592-1.324 1.323-.594C31.201 19.384 31.823 17.757 31.202 16.369zM13.623 21.215l-3.395-7.593 7.591-3.394 3.395 7.591L13.623 21.215z"/></svg></a></div><div class=icon><span>twitter</span>
<a title="Follow us on Twitter to get the latest news" href=https://twitter.com/IstioMesh aria-label=Twitter><svg viewBox="0 0 310 310"><path d="M302.973 57.388c-4.87 2.16-9.877 3.983-14.993 5.463 6.057-6.85 10.675-14.91 13.494-23.73.632-1.977-.023-4.141-1.648-5.434-1.623-1.294-3.878-1.449-5.665-.39-10.865 6.444-22.587 11.075-34.878 13.783-12.381-12.098-29.197-18.983-46.581-18.983-36.695.0-66.549 29.853-66.549 66.547.0 2.89.183 5.764.545 8.598C101.163 99.244 58.83 76.863 29.76 41.204c-1.036-1.271-2.632-1.956-4.266-1.825-1.635.128-3.104 1.05-3.93 2.467-5.896 10.117-9.013 21.688-9.013 33.461.0 16.035 5.725 31.249 15.838 43.137-3.075-1.065-6.059-2.396-8.907-3.977-1.529-.851-3.395-.838-4.914.033-1.52.871-2.473 2.473-2.513 4.224-.007.295-.007.59-.007.889.0 23.935 12.882 45.484 32.577 57.229-1.692-.169-3.383-.414-5.063-.735-1.732-.331-3.513.276-4.681 1.597-1.17 1.32-1.557 3.16-1.018 4.84 7.29 22.76 26.059 39.501 48.749 44.605-18.819 11.787-40.34 17.961-62.932 17.961-4.714.0-9.455-.277-14.095-.826-2.305-.274-4.509 1.087-5.294 3.279-.785 2.193.047 4.638 2.008 5.895 29.023 18.609 62.582 28.445 97.047 28.445 67.754.0 110.139-31.95 133.764-58.753 29.46-33.421 46.356-77.658 46.356-121.367.0-1.826-.028-3.67-.084-5.508 11.623-8.757 21.63-19.355 29.773-31.536 1.237-1.85 1.103-4.295-.33-5.998C307.394 57.037 305.009 56.486 302.973 57.388z"/></svg></a></div><div class=icon><span>stack overflow</span>
<a title="Stack Overflow is where you can ask questions and find curated answers on deploying, configuring, and using Istio" href=https://stackoverflow.com/questions/tagged/istio aria-label="Stack Overflow"><svg viewBox="0 0 120 120"><polygon points="84.4,93.8 84.4,70.6 92.1,70.6 92.1,101.5 22.6,101.5 22.6,70.6 30.3,70.6 30.3,93.8"/><path d="M38.8 68.4l37.8 7.9 1.6-7.6-37.8-7.9L38.8 68.4zM43.8 50.4l35 16.3 3.2-7-35-16.4L43.8 50.4zM53.5 33.2l29.7 24.7 4.9-5.9L58.4 27.3 53.5 33.2zM72.7 14.9l-6.2 4.6 23 31 6.2-4.6-23-31zM38 86h38.6v-7.7H38V86z"/></svg></a></div></div><div class="tag row d-none d-lg-flex">for everyone</div></div></div><div class="col-7 col-lg-4"><p class="text-center copyright" role=contentinfo>Istio
Archive
1.0<br>&copy; 2019 Istio Authors, <a href=https://policies.google.com/privacy>Privacy Policy</a><br>Archived on March 19, 2019</p></div><div class="col-6 col-lg-4 d-none d-lg-flex" role=navigation><div class=container-fluid><div class="row justify-content-end"><div class=icon><span>github</span>
<a title="GitHub is where development takes place on Istio code" href=https://github.com/istio/community aria-label=GitHub><svg viewBox="0 0 478.165 478.165"><path d="M349.22 55.768c6.136 14.046 10.241 37.556 4.224 54.69 24.426 20.999 33.073 71.904 21.079 113.704 35.006 2.73 76.666-1.235 103.642 9.484-25.183-3.248-59.651-9.563-91.987-7.431-6.136.458-15.361-.239-14.903 8.408 37.735 3.008 75.092 6.117 105.894 15.779-30.702-4.981-67.74-12.552-105.894-13.668-15.54 30.921-47.239 46.262-90.991 49.49 4.682 10.261 13.847 14.066 15.879 30.702 3.267 24.406-4.881 60.328 3.208 76.686 4.064 7.89 10.579 8.009 14.863 14.604-10.699 12.871-37.257-1.395-40.186-14.604-5.14-22.852 7.89-58.256-6.415-73.737.996 24.865-5.718 59.85.996 82.145 2.789 8.806 10.659 12.113 8.647 20.063-49.809 5.08-28.989-64.373-37.177-105.356-7.471.697-4.204 11.197-4.224 15.76-.199 40.106 8.189 94.836-34.846 89.556-1.315-8.348 5.838-11.217 8.467-19.007 7.91-22.434-1.454-56.045 2.112-83.161-16.417 12.512 1.793 55.666-8.428 77.961-5.838 12.671-24.785 18.27-39.19 12.651 1.873-9.464 11.695-7.989 15.879-16.875 5.818-12.452.02-30.244 2.092-48.494-30.423 6.097-53.993-.877-65.608-20.023-5.12-8.507-6.356-18.708-12.632-26.219-6.117-7.551-16.098-8.507-19.087-18.808 37.755-9.185 39.17 38.771 73.06 39.807 10.44.418 15.799-2.909 25.402-5.16 2.749-12.113 8.428-21.039 16.875-27.494-42.078-5.658-76.865-18.788-93.023-50.466-38.293 1.893-73.339 7.013-105.894 14.843 29.547-10.679 65.807-14.604 104.778-15.819-2.351-13.807-22.434-10.022-34.866-9.543C47.677 227.17 18.449 230.138.0 233.645c26.817-9.543 64.233-8.348 100.454-8.428-11.038-34.767-7.232-90.014 17.015-110.615-6.854-17.254-4.722-45.346 4.184-58.834 27.036 1.175 43.374 12.891 60.388 24.247 21.019-6.017 43.035-9.045 71.904-7.451 12.133.677 24.705 6.097 33.731 5.32 8.906-.877 18.728-10.898 27.534-14.843C326.507 58.099 336.17 56.206 349.22 55.768z"/></svg></a></div><div class=icon><span>drive</span>
<a title="Access our team drive if you'd like to take a look at the Istio technical design documents" href=https://groups.google.com/forum/#!forum/istio-team-drive-access aria-label="team drive"><svg viewBox="0 0 207.027 207.027"><path d="M69.866 15.557.0 138.919l28.732 52.552 143.288-.029 35.008-59.588L136.39 15.735 69.866 15.557zM17.166 139.046 74.268 38.205 91.21 67.783 33.24 168.447 17.166 139.046zM99.841 82.851l23.805 41.558-47.732-.006L99.841 82.851zM163.434 176.443l-117.332.024 21.53-37.065 64.606.008.067.119 52.865-.085L163.434 176.443zM140.932 124.411 90.157 35.767l-2.966-5.178 40.751.121 57.003 93.706L140.932 124.411z"/></svg></a></div><div class=icon><span>working groups</span>
<a title="If you'd like to contribute to the Istio project, consider participating in our working groups" href=https://github.com/istio/community/blob/master/WORKING-GROUPS.md aria-label="working groups"><svg viewBox="0 -45 439.833 439.833"><polygon points="246.048,195.833 299.966,235.085 319.497,227.296 276.278,195.833"/><polygon points="193.786,195.833 163.556,195.833 120.33,227.3 139.862,235.089"/><path d="M219.927 11.558c-23.854.0-37.057 12.362-36.814 36.182.348 32.623 14.211 52.414 36.814 52.068.0.0 36.802 1.492 36.802-52.068C256.729 23.918 244.294 11.558 219.927 11.558z"/><path d="M285.017 124.567l-36.77-14.659-8.608-7.256c-2.274-1.922-5.636-1.78-7.741.317l-11.973 11.904-12.008-11.907c-2.109-2.094-5.465-2.229-7.736-.313l-8.611 7.256-36.77 14.661c-11.842 4.715-11.83 46.647-12.848 50.497h155.93C296.866 171.228 296.862 129.28 285.017 124.567z"/><path d="M77.976 228.568s36.801 1.492 36.801-52.068c0-23.82-12.434-36.182-36.801-36.182-23.854.0-37.057 12.362-36.814 36.182C41.509 209.124 55.372 228.915 77.976 228.568z"/><path d="M143.065 253.329l-36.77-14.658-8.609-7.256c-2.275-1.923-5.635-1.781-7.742.315l-11.971 11.904-12.008-11.908c-2.109-2.094-5.465-2.229-7.736-.312l-8.611 7.256-36.77 14.66C1.006 258.045 1.018 299.977.0 303.827h155.93C154.915 299.988 154.911 258.042 143.065 253.329z"/><path d="M361.878 228.568s36.801 1.492 36.801-52.068c0-23.82-12.434-36.182-36.801-36.182-23.854.0-37.057 12.362-36.812 36.182C325.411 209.124 339.274 228.915 361.878 228.568z"/><path d="M426.968 253.329l-36.77-14.658-8.609-7.256c-2.273-1.923-5.635-1.781-7.742.315l-11.971 11.904-12.008-11.908c-2.109-2.094-5.465-2.229-7.736-.312l-8.61 7.256-36.771 14.66c-11.842 4.715-11.83 46.646-12.848 50.497h155.93C438.817 299.988 438.812 258.042 426.968 253.329z"/></svg></a></div></div><div class="tag row justify-content-end text-right">for developers</div></div></div></div></footer><div class="d-xl-none d-print-none"><button id=scroll-to-top aria-hidden=true onclick=scrollToTop() title="Back to top"><i class="fa fa-lg fa-arrow-up"></i></button></div><script src=https://code.jquery.com/jquery-3.2.1.slim.min.js integrity=sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN crossorigin=anonymous></script><script src=https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js integrity=sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl crossorigin=anonymous></script><script src=https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js></script><script src="https://www.google.com/cse/brand?form=search_form"></script><script src=/v1.0/js/all.min.js data-manual></script></body></html>