CINXE.COM
Using Recommendations for Infrastructure as Code | Recommender Documentation | Google Cloud
<!doctype html> <html lang="en" dir="ltr"> <head> <meta name="google-signin-client-id" content="721724668570-nbkv1cfusk7kk4eni4pjvepaus73b13t.apps.googleusercontent.com"> <meta name="google-signin-scope" content="profile email https://www.googleapis.com/auth/developerprofiles https://www.googleapis.com/auth/developerprofiles.award https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/webhistory"> <meta property="og:site_name" content="Google Cloud"> <meta property="og:type" content="website"><meta name="theme-color" content="#039be5"><meta charset="utf-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="manifest" href="/_pwa/cloud/manifest.json" crossorigin="use-credentials"> <link rel="preconnect" href="//www.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.googleapis.com" crossorigin> <link rel="preconnect" href="//apis.google.com" crossorigin> <link rel="preconnect" href="//www.google-analytics.com" crossorigin><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Google+Sans:400,500,700|Google+Sans+Text:400,400italic,500,500italic,700,700italic|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"> <link rel="stylesheet" href="//fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined&display=block"><link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/css/app.css"> <link rel="shortcut icon" href="https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/images/favicons/onecloud/favicon.ico"> <link rel="apple-touch-icon" href="https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/images/favicons/onecloud/super_cloud.png"><link rel="canonical" href="https://cloud.google.com/recommender/docs/tutorial-iac"><link rel="search" type="application/opensearchdescription+xml" title="Google Cloud" href="https://cloud.google.com/s/opensearch.xml"> <link rel="alternate" hreflang="en" href="https://cloud.google.com/recommender/docs/tutorial-iac" /><link rel="alternate" hreflang="x-default" href="https://cloud.google.com/recommender/docs/tutorial-iac" /><link rel="alternate" hreflang="zh-Hans" href="https://cloud.google.com/recommender/docs/tutorial-iac?hl=zh-cn" /><link rel="alternate" hreflang="fr" href="https://cloud.google.com/recommender/docs/tutorial-iac?hl=fr" /><link rel="alternate" hreflang="de" href="https://cloud.google.com/recommender/docs/tutorial-iac?hl=de" /><link rel="alternate" hreflang="id" href="https://cloud.google.com/recommender/docs/tutorial-iac?hl=id" /><link rel="alternate" hreflang="it" href="https://cloud.google.com/recommender/docs/tutorial-iac?hl=it" /><link rel="alternate" hreflang="ja" href="https://cloud.google.com/recommender/docs/tutorial-iac?hl=ja" /><link rel="alternate" hreflang="ko" href="https://cloud.google.com/recommender/docs/tutorial-iac?hl=ko" /><link rel="alternate" hreflang="pt-BR" href="https://cloud.google.com/recommender/docs/tutorial-iac?hl=pt-br" /><link rel="alternate" hreflang="es-419" href="https://cloud.google.com/recommender/docs/tutorial-iac?hl=es-419" /><title>Using Recommendations for Infrastructure as Code | Recommender Documentation | Google Cloud</title> <meta property="og:title" content="Using Recommendations for Infrastructure as Code | Recommender Documentation | Google Cloud"><meta property="og:url" content="https://cloud.google.com/recommender/docs/tutorial-iac"><meta property="og:image" content="https://cloud.google.com/_static/cloud/images/social-icon-google-cloud-1200-630.png"> <meta property="og:image:width" content="1200"> <meta property="og:image:height" content="630"><meta property="og:locale" content="en"><meta name="twitter:card" content="summary_large_image"><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "Using Recommendations for Infrastructure as Code" } </script><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{ "@type": "ListItem", "position": 1, "name": "Recommender", "item": "https://cloud.google.com/recommender/docs" },{ "@type": "ListItem", "position": 2, "name": "Documentation", "item": "https://cloud.google.com/recommender/docs/whatis-activeassist" },{ "@type": "ListItem", "position": 3, "name": "Using Recommendations for Infrastructure as Code", "item": "https://cloud.google.com/recommender/docs/tutorial-iac" }] } </script> <meta name="gtm_var" data-key="docType" data-value="tutorial"> <link rel="stylesheet" href="/extras.css"></head> <body class="" template="page" theme="cloud-theme" type="article" layout="docs" free-trial display-toc pending> <devsite-progress type="indeterminate" id="app-progress"></devsite-progress> <a href="#main-content" class="skip-link button"> Skip to main content </a> <section class="devsite-wrapper"> <devsite-cookie-notification-bar></devsite-cookie-notification-bar><cloudx-track userCountry="SG"></cloudx-track> <cloudx-utils-init></cloudx-utils-init> <devsite-header keep-tabs-visible> <div class="devsite-header--inner nocontent"> <div class="devsite-top-logo-row-wrapper-wrapper"> <div class="devsite-top-logo-row-wrapper"> <div class="devsite-top-logo-row"> <button type="button" id="devsite-hamburger-menu" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Navigation menu button" visually-hidden aria-label="Open menu"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="googleCloud" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <img src="https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/images/cloud-logo.svg" class="devsite-site-logo" alt="Google Cloud"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item devsite-has-google-wordmark"> </li> </ul> </span> </div> <div class="devsite-top-logo-row-middle"> <div class="devsite-header-upper-tabs"> <cloudx-tabs-nav class="upper-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Upper tabs"> <tab class="devsite-active"> <a href="https://cloud.google.com/docs" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://cloud.google.com/docs" track-type="nav" track-metadata-position="nav - docs-home" track-metadata-module="primary nav" aria-label="Documentation, selected" data-category="Site-Wide Custom Events" data-label="Tab: Documentation" track-name="docs-home" track-link-column-type="single-column" > Documentation </a> </tab> <tab class="devsite-dropdown devsite-clickable "> <a href="https://cloud.google.com/docs/tech-area-overviews" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://cloud.google.com/docs/tech-area-overviews" track-type="nav" track-metadata-position="nav - technology-areas" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Technology areas" track-name="technology-areas" track-link-column-type="single-column" > Technology areas </a> <button aria-haspopup="menu" aria-expanded="false" aria-label="Dropdown menu for Technology areas" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/tech-area-overviews" track-metadata-position="nav - technology-areas" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Technology areas" track-name="technology-areas" track-link-column-type="single-column" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></button> <div class="devsite-tabs-dropdown" role="menu" aria-label="submenu" hidden> <button class="devsite-tabs-close-button material-icons button-flat gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close dropdown menu" aria-label="Close dropdown menu" track-type="nav" track-name="close" track-metadata-eventdetail="#" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav">close</button> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column "> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/ai-ml" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/ai-ml" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> AI and ML </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/application-development" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/application-development" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Application development </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/application-hosting" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/application-hosting" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Application hosting </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/compute-area" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/compute-area" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Compute </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/data" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/data" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Data analytics and pipelines </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/databases" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/databases" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Databases </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/dhm-cloud" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/dhm-cloud" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Distributed, hybrid, and multicloud </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/generative-ai" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/generative-ai" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Generative AI </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/industry" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/industry" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Industry solutions </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/networking" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/networking" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Networking </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/observability" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/observability" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Observability and monitoring </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/security" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/security" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Security </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/storage" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/storage" track-metadata-position="nav - technology-areas" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Storage </div> </a> </li> </ul> </div> </div> </div> </tab> <tab class="devsite-dropdown devsite-clickable "> <a href="https://cloud.google.com/docs/cross-product-overviews" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://cloud.google.com/docs/cross-product-overviews" track-type="nav" track-metadata-position="nav - crossproduct" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Cross-product tools" track-name="crossproduct" track-link-column-type="single-column" > Cross-product tools </a> <button aria-haspopup="menu" aria-expanded="false" aria-label="Dropdown menu for Cross-product tools" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/cross-product-overviews" track-metadata-position="nav - crossproduct" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Cross-product tools" track-name="crossproduct" track-link-column-type="single-column" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></button> <div class="devsite-tabs-dropdown" role="menu" aria-label="submenu" hidden> <button class="devsite-tabs-close-button material-icons button-flat gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close dropdown menu" aria-label="Close dropdown menu" track-type="nav" track-name="close" track-metadata-eventdetail="#" track-metadata-position="nav - crossproduct" track-metadata-module="tertiary nav">close</button> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column "> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/access-resources" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/access-resources" track-metadata-position="nav - crossproduct" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Access and resources management </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/costs-usage" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/costs-usage" track-metadata-position="nav - crossproduct" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Costs and usage management </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/devtools" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/devtools" track-metadata-position="nav - crossproduct" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Google Cloud SDK, languages, frameworks, and tools </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/iac" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/iac" track-metadata-position="nav - crossproduct" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Infrastructure as code </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/docs/migration" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/docs/migration" track-metadata-position="nav - crossproduct" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Migration </div> </a> </li> </ul> </div> </div> </div> </tab> <tab class="devsite-dropdown devsite-clickable "> <a href="https://cloud.google.com/" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://cloud.google.com/" track-type="nav" track-metadata-position="nav - related-sites" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Related sites" track-name="related-sites" track-link-column-type="single-column" > Related sites </a> <button aria-haspopup="menu" aria-expanded="false" aria-label="Dropdown menu for Related sites" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/" track-metadata-position="nav - related-sites" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Related sites" track-name="related-sites" track-link-column-type="single-column" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></button> <div class="devsite-tabs-dropdown" role="menu" aria-label="submenu" hidden> <button class="devsite-tabs-close-button material-icons button-flat gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close dropdown menu" aria-label="Close dropdown menu" track-type="nav" track-name="close" track-metadata-eventdetail="#" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav">close</button> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column "> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-item"> <a href="https://cloud.google.com/" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Google Cloud Home </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/free" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/free" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Free Trial and Free Tier </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/architecture" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/architecture" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Architecture Center </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/blog" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/blog" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Blog </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/contact" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/contact" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Contact Sales </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/developers" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/developers" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Google Cloud Developer Center </div> </a> </li> <li class="devsite-nav-item"> <a href="https://developers.google.com/" track-type="nav" track-metadata-eventdetail="https://developers.google.com/" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Google Developer Center </div> </a> </li> <li class="devsite-nav-item"> <a href="https://console.cloud.google.com/marketplace" track-type="nav" track-metadata-eventdetail="https://console.cloud.google.com/marketplace" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Google Cloud Marketplace </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/marketplace/docs" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/marketplace/docs" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Google Cloud Marketplace Documentation </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.cloudskillsboost.google/paths" track-type="nav" track-metadata-eventdetail="https://www.cloudskillsboost.google/paths" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Google Cloud Skills Boost </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/solutions" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/solutions" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Google Cloud Solution Center </div> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/support-hub" track-type="nav" track-metadata-eventdetail="https://cloud.google.com/support-hub" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Google Cloud Support </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.youtube.com/@googlecloudtech" track-type="nav" track-metadata-eventdetail="https://www.youtube.com/@googlecloudtech" track-metadata-position="nav - related-sites" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Google Cloud Tech Youtube Channel </div> </a> </li> </ul> </div> </div> </div> </tab> </nav> </cloudx-tabs-nav> </div> <devsite-search enable-signin enable-search enable-suggestions project-name="Recommender Documentation" tenant-name="Google Cloud" project-scope="/recommender/docs/whatis-activeassist" url-scoped="https://cloud.google.com/s/results/recommender/docs/whatis-activeassist" > <form class="devsite-search-form" action="https://cloud.google.com/s/results" method="GET"> <div class="devsite-search-container"> <button type="button" search-open class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Open search"></button> <div class="devsite-searchbox"> <input aria-activedescendant="" aria-autocomplete="list" aria-label="Search" aria-expanded="false" aria-haspopup="listbox" autocomplete="off" class="devsite-search-field devsite-search-query" name="q" placeholder="Search" role="combobox" type="text" value="" > <div class="devsite-search-image material-icons" aria-hidden="true"> </div> <div class="devsite-search-shortcut-icon-container" aria-hidden="true"> <kbd class="devsite-search-shortcut-icon">/</kbd> </div> </div> </div> </form> <button type="button" search-close class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Close search"></button> </devsite-search> </div> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> <devsite-user enable-profiles fp-auth id="devsite-user"> <span class="button devsite-top-button" aria-hidden="true" visually-hidden>Sign in</span> </devsite-user> </div> </div> </div> <div class="devsite-collapsible-section "> <div class="devsite-header-background"> <div class="devsite-product-id-row" hidden> <div class="devsite-product-description-row"> </div> </div> <div class="devsite-doc-set-nav-row"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> <a href="https://cloud.google.com/recommender/docs" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Lower Header" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="Recommender" > Recommender </a> </li> </ul> <cloudx-tabs-nav class="lower-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Lower tabs"> <tab > <a href="https://cloud.google.com/recommender/docs/whatis-activeassist" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://cloud.google.com/recommender/docs/whatis-activeassist" track-type="nav" track-metadata-position="nav - overview" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Overview" track-name="overview" > Overview </a> </tab> <tab class="devsite-active"> <a href="https://cloud.google.com/recommender/docs" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://cloud.google.com/recommender/docs" track-type="nav" track-metadata-position="nav - guides" track-metadata-module="primary nav" aria-label="Guides, selected" data-category="Site-Wide Custom Events" data-label="Tab: Guides" track-name="guides" > Guides </a> </tab> <tab > <a href="https://cloud.google.com/recommender/docs/apis" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://cloud.google.com/recommender/docs/apis" track-type="nav" track-metadata-position="nav - reference" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Reference" track-name="reference" > Reference </a> </tab> <tab > <a href="https://cloud.google.com/recommender/docs/resources" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://cloud.google.com/recommender/docs/resources" track-type="nav" track-metadata-position="nav - resources" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Resources" track-name="resources" > Resources </a> </tab> </nav> </cloudx-tabs-nav> <div class="devsite-product-button-row"> <a href="https://cloud.google.com/contact" class="cta-button-secondary button " track-type="contact" data-overflow-wrapper="tab" track-metadata-position="nav" data-overflow-container="left" data-overflow="devsite-tabs-wrapper" track-metadata-eventDetail="nav" track-name="sales" >Contact Us</a> <a href="//console.cloud.google.com/freetrial" class="cloud-free-trial-button cta-button-primary button-primary button cloud-button cloud-button--primary " track-type="freeTrial" data-overflow="devsite-top-logo-row" track-name="gcpCta" data-overflow-class="devsite-header-link devsite-top-button button cloud-free-trial-button cloud-free-trial-enabled cloud-button cloud-button--primary" data-overflow-container="right" track-metadata-position="nav" referrerpolicy="no-referrer-when-downgrade" track-metadata-eventDetail="nav" >Start free</a> </div> </div> </div> </div> </div> </devsite-header> <devsite-book-nav scrollbars > <div class="devsite-book-nav-filter" > <span class="filter-list-icon material-icons" aria-hidden="true"></span> <input type="text" placeholder="Filter" aria-label="Type to filter" role="searchbox"> <span class="filter-clear-button hidden" data-title="Clear filter" aria-label="Clear filter" role="button" tabindex="0"></span> </div> <nav class="devsite-book-nav devsite-nav nocontent" aria-label="Side menu"> <div class="devsite-mobile-header"> <button type="button" id="devsite-close-nav" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close navigation" aria-label="Close navigation"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="googleCloud" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <img src="https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/images/cloud-logo.svg" class="devsite-site-logo" alt="Google Cloud"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item devsite-has-google-wordmark"> </li> </ul> </span> </div> </div> <div class="devsite-book-nav-wrapper"> <div class="devsite-mobile-nav-top"> <ul class="devsite-nav-list"> <li class="devsite-nav-item"> <a href="/docs" class="devsite-nav-title gc-analytics-event devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Documentation" track-name="docs-home" track-link-column-type="single-column" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Documentation" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Documentation </span> </a> <ul class="devsite-nav-responsive-tabs"> <li class="devsite-nav-item"> <a href="/recommender/docs/whatis-activeassist" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Overview" track-name="overview" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> </a> </li> <li class="devsite-nav-item"> <a href="/recommender/docs" class="devsite-nav-title gc-analytics-event devsite-nav-has-children devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Guides" track-name="guides" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Guides" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip menu="_book"> Guides </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="_book"> </span> </a> </li> <li class="devsite-nav-item"> <a href="/recommender/docs/apis" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Reference" track-name="reference" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Reference" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Reference </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/recommender/docs/resources" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Resources" track-name="resources" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Resources" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Resources </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/docs/tech-area-overviews" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Technology areas" track-name="technology-areas" track-link-column-type="single-column" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Technology areas" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Technology areas </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Technology areas" track-name="technology-areas" track-link-column-type="single-column" > <span class="devsite-nav-text" tooltip menu="Technology areas"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Technology areas"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/docs/cross-product-overviews" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Cross-product tools" track-name="crossproduct" track-link-column-type="single-column" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Cross-product tools" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Cross-product tools </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Cross-product tools" track-name="crossproduct" track-link-column-type="single-column" > <span class="devsite-nav-text" tooltip menu="Cross-product tools"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Cross-product tools"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Related sites" track-name="related-sites" track-link-column-type="single-column" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Related sites" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Related sites </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Related sites" track-name="related-sites" track-link-column-type="single-column" > <span class="devsite-nav-text" tooltip menu="Related sites"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Related sites"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="//console.cloud.google.com/" class="devsite-nav-title gc-analytics-event " track-name="console" track-metadata-position="nav" referrerpolicy="no-referrer-when-downgrade" track-metadata-eventDetail="nav" track-type="globalNav" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Console" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Console </span> </a> </li> <li class="devsite-nav-item"> <a href="/contact" class="cta-button-secondary button" track-type="contact" data-overflow-wrapper="tab" track-metadata-position="nav" data-overflow-container="left" data-overflow="devsite-tabs-wrapper" track-metadata-eventDetail="nav" track-name="sales" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Contact Us" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Contact Us </span> </a> </li> <li class="devsite-nav-item"> <a href="//console.cloud.google.com/freetrial" class="cloud-free-trial-button cta-button-primary button-primary button cloud-button cloud-button--primary" track-type="freeTrial" data-overflow="devsite-top-logo-row" track-name="gcpCta" data-overflow-class="devsite-header-link devsite-top-button button cloud-free-trial-button cloud-free-trial-enabled cloud-button cloud-button--primary" data-overflow-container="right" track-metadata-position="nav" referrerpolicy="no-referrer-when-downgrade" track-metadata-eventDetail="nav" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Start free" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Start free </span> </a> </li> </ul> </div> <div class="devsite-mobile-nav-bottom"> <ul class="devsite-nav-list" menu="_book"> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Discover</span> </div></li> <li class="devsite-nav-item"><a href="/recommender/docs/whatis-activeassist" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/whatis-activeassist" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/whatis-activeassist" ><span class="devsite-nav-text" tooltip>What is Active Assist</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/understand-cost-recs" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/understand-cost-recs" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/understand-cost-recs" ><span class="devsite-nav-text" tooltip>Understand how cost savings are calculated in Active Assist recommendations</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Get started</span> </div></li> <li class="devsite-nav-item devsite-nav-expandable"><div class="devsite-expandable-nav"> <a class="devsite-nav-toggle" aria-hidden="true"></a><div class="devsite-nav-title devsite-nav-title-no-path" tabindex="0" role="button"> <span class="devsite-nav-text" tooltip>Quickstarts</span> </div><ul class="devsite-nav-section"><li class="devsite-nav-item"><a href="/recommender/docs/quickstart-recommendation-hub" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/quickstart-recommendation-hub" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/quickstart-recommendation-hub" ><span class="devsite-nav-text" tooltip>Find recommendations in the Recommendation Hub</span></a></li><li class="devsite-nav-item"><a href="/recommender/docs/quickstart-incontext" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/quickstart-incontext" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/quickstart-incontext" ><span class="devsite-nav-text" tooltip>Find recommendations in context</span></a></li></ul></div></li> <li class="devsite-nav-item devsite-nav-expandable"><div class="devsite-expandable-nav"> <a class="devsite-nav-toggle" aria-hidden="true"></a><div class="devsite-nav-title devsite-nav-title-no-path" tabindex="0" role="button"> <span class="devsite-nav-text" tooltip>Using the API</span> </div><ul class="devsite-nav-section"><li class="devsite-nav-item"><a href="/recommender/docs/enable-api" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/enable-api" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/enable-api" ><span class="devsite-nav-text" tooltip>Enable the API</span></a></li><li class="devsite-nav-item"><a href="/recommender/docs/use-api" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/use-api" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/use-api" ><span class="devsite-nav-text" tooltip>Recommendations</span></a></li><li class="devsite-nav-item"><a href="/recommender/docs/insights/use-api" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/insights/use-api" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/insights/use-api" ><span class="devsite-nav-text" tooltip>Insights</span></a></li></ul></div></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Recommendation Hub</span> </div></li> <li class="devsite-nav-item"><a href="/recommender/docs/recommendation-hub/find-recommnedation-hub" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/recommendation-hub/find-recommnedation-hub" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/recommendation-hub/find-recommnedation-hub" ><span class="devsite-nav-text" tooltip>Find the Recommendation Hub</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/recommendation-hub/adjust-scope" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/recommendation-hub/adjust-scope" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/recommendation-hub/adjust-scope" ><span class="devsite-nav-text" tooltip>Adjust the scope of your recommendations</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/recommendation-hub/dashboard-overview" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/recommendation-hub/dashboard-overview" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/recommendation-hub/dashboard-overview" ><span class="devsite-nav-text" tooltip>Dashboard overview</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/recommendation-hub/find-recommendations" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/recommendation-hub/find-recommendations" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/recommendation-hub/find-recommendations" ><span class="devsite-nav-text" tooltip>Find recommendations</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/recommendation-hub/share-recommendations" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/recommendation-hub/share-recommendations" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/recommendation-hub/share-recommendations" ><span class="devsite-nav-text" tooltip>Share recommendations</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/recommendation-hub/apply-dismiss-restore-recommendations" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/recommendation-hub/apply-dismiss-restore-recommendations" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/recommendation-hub/apply-dismiss-restore-recommendations" ><span class="devsite-nav-text" tooltip>Apply, dismiss, and restore recommendations</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Insights and recommendations</span> </div></li> <li class="devsite-nav-item"><a href="/recommender/docs/insights/using-insights" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/insights/using-insights" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/insights/using-insights" ><span class="devsite-nav-text" tooltip>Insights</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/key-concepts" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/key-concepts" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/key-concepts" ><span class="devsite-nav-text" tooltip>Recommendations</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/opt-out" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/opt-out" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/opt-out" ><span class="devsite-nav-text" tooltip>Opt out of insights and recommendations</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/viewing-logs" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/viewing-logs" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/viewing-logs" ><span class="devsite-nav-text" tooltip>View logs</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/audit-logging" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/audit-logging" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/audit-logging" ><span class="devsite-nav-text" tooltip>Use Cloud Audit Logs for Recommender</span></a></li> <li class="devsite-nav-item"><a href="/recommender/docs/bq-export/export-recommendations-to-bq" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/bq-export/export-recommendations-to-bq" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/bq-export/export-recommendations-to-bq" ><span class="devsite-nav-text" tooltip>Export insights and recommendations to BigQuery</span></a></li> <li class="devsite-nav-item devsite-nav-expandable"><div class="devsite-expandable-nav"> <a class="devsite-nav-toggle" aria-hidden="true"></a><div class="devsite-nav-title devsite-nav-title-no-path" tabindex="0" role="button"> <span class="devsite-nav-text" tooltip>Transparency and Control Center</span> </div><ul class="devsite-nav-section"><li class="devsite-nav-item"><a href="/recommender/docs/transparency-and-control-center/audit-logging" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/transparency-and-control-center/audit-logging" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/transparency-and-control-center/audit-logging" ><span class="devsite-nav-text" tooltip>Audit logging</span></a></li><li class="devsite-nav-item"><a href="/recommender/docs/transparency-and-control-center/exporting-data" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/transparency-and-control-center/exporting-data" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/transparency-and-control-center/exporting-data" ><span class="devsite-nav-text" tooltip>Data export</span></a></li><li class="devsite-nav-item"><a href="/recommender/docs/transparency-and-control-center/access-control" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/transparency-and-control-center/access-control" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/transparency-and-control-center/access-control" ><span class="devsite-nav-text" tooltip>Access control</span></a></li></ul></div></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Tutorials</span> </div></li> <li class="devsite-nav-item"><a href="/recommender/docs/tutorial-iac" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/tutorial-iac" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/tutorial-iac" ><span class="devsite-nav-text" tooltip>Use Recommendations for Infrastructure as Code</span></a></li> <li class="devsite-nav-item devsite-nav-expandable"><div class="devsite-expandable-nav"> <a class="devsite-nav-toggle" aria-hidden="true"></a><div class="devsite-nav-title devsite-nav-title-no-path" tabindex="0" role="button"> <span class="devsite-nav-text" tooltip>Active Assist at scale</span> </div><ul class="devsite-nav-section"><li class="devsite-nav-item"><a href="/recommender/docs/patterns-for-using-active-assist-at-scale" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/patterns-for-using-active-assist-at-scale" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/patterns-for-using-active-assist-at-scale" ><span class="devsite-nav-text" tooltip>Patterns for using Active Assist at scale</span></a></li><li class="devsite-nav-item"><a href="/recommender/docs/using-serverless-pipelines-with-active-assist" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/using-serverless-pipelines-with-active-assist" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/using-serverless-pipelines-with-active-assist" ><span class="devsite-nav-text" tooltip>Use serverless pipelines with Active Assist</span></a></li><li class="devsite-nav-item"><a href="/recommender/docs/use-anthos-toolchain-with-active-assist" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommender/docs/use-anthos-toolchain-with-active-assist" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommender/docs/use-anthos-toolchain-with-active-assist" ><span class="devsite-nav-text" tooltip>Use the GKE Enterprise toolchain with Active Assist</span></a></li></ul></div></li> <li class="devsite-nav-item devsite-nav-external"><a href="https://cloud.google.com/blog/topics/developers-practitioners/automated-cleanup-unused-google-cloud-projects/" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: https://cloud.google.com/blog/topics/developers-practitioners/automated-cleanup-unused-google-cloud-projects/" track-type="bookNav" track-name="click" track-metadata-eventdetail="https://cloud.google.com/blog/topics/developers-practitioners/automated-cleanup-unused-google-cloud-projects/" ><span class="devsite-nav-text" tooltip>Automated Cleanup of Unused Google Cloud Projects</span><span class="devsite-nav-icon material-icons" data-icon="external" data-title="External" aria-hidden="true"></span></a></li> </ul> <ul class="devsite-nav-list" menu="Technology areas" aria-label="Side menu" hidden> <li class="devsite-nav-item"> <a href="/docs/ai-ml" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: AI and ML" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > AI and ML </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/application-development" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Application development" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Application development </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/application-hosting" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Application hosting" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Application hosting </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/compute-area" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Compute" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Compute </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/data" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Data analytics and pipelines" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Data analytics and pipelines </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/databases" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Databases" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Databases </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/dhm-cloud" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Distributed, hybrid, and multicloud" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Distributed, hybrid, and multicloud </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/generative-ai" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Generative AI" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Generative AI </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/industry" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Industry solutions" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Industry solutions </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/networking" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Networking" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Networking </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/observability" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Observability and monitoring" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Observability and monitoring </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/security" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Security" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Security </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/storage" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Storage" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Storage </span> </a> </li> </ul> <ul class="devsite-nav-list" menu="Cross-product tools" aria-label="Side menu" hidden> <li class="devsite-nav-item"> <a href="/docs/access-resources" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Access and resources management" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Access and resources management </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/costs-usage" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Costs and usage management" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Costs and usage management </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/devtools" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Cloud SDK, languages, frameworks, and tools" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Cloud SDK, languages, frameworks, and tools </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/iac" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Infrastructure as code" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Infrastructure as code </span> </a> </li> <li class="devsite-nav-item"> <a href="/docs/migration" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Migration" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Migration </span> </a> </li> </ul> <ul class="devsite-nav-list" menu="Related sites" aria-label="Side menu" hidden> <li class="devsite-nav-item"> <a href="/" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Cloud Home" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Cloud Home </span> </a> </li> <li class="devsite-nav-item"> <a href="/free" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Free Trial and Free Tier" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Free Trial and Free Tier </span> </a> </li> <li class="devsite-nav-item"> <a href="/architecture" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Architecture Center" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Architecture Center </span> </a> </li> <li class="devsite-nav-item"> <a href="https://cloud.google.com/blog" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Blog" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Blog </span> </a> </li> <li class="devsite-nav-item"> <a href="/contact" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Contact Sales" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Contact Sales </span> </a> </li> <li class="devsite-nav-item"> <a href="/developers" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Cloud Developer Center" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Cloud Developer Center </span> </a> </li> <li class="devsite-nav-item"> <a href="https://developers.google.com/" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Developer Center" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Developer Center </span> </a> </li> <li class="devsite-nav-item"> <a href="https://console.cloud.google.com/marketplace" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Cloud Marketplace" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Cloud Marketplace </span> </a> </li> <li class="devsite-nav-item"> <a href="/marketplace/docs" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Cloud Marketplace Documentation" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Cloud Marketplace Documentation </span> </a> </li> <li class="devsite-nav-item"> <a href="https://www.cloudskillsboost.google/paths" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Cloud Skills Boost" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Cloud Skills Boost </span> </a> </li> <li class="devsite-nav-item"> <a href="/solutions" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Cloud Solution Center" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Cloud Solution Center </span> </a> </li> <li class="devsite-nav-item"> <a href="/support-hub" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Cloud Support" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Cloud Support </span> </a> </li> <li class="devsite-nav-item"> <a href="https://www.youtube.com/@googlecloudtech" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Google Cloud Tech Youtube Channel" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Google Cloud Tech Youtube Channel </span> </a> </li> </ul> </div> </div> </nav> </devsite-book-nav> <section id="gc-wrapper"> <main role="main" id="main-content" class="devsite-main-content" has-book-nav has-sidebar > <div class="devsite-sidebar"> <div class="devsite-sidebar-content"> <devsite-toc class="devsite-nav" role="navigation" aria-label="On this page" depth="2" scrollbars ></devsite-toc> <devsite-recommendations-sidebar class="nocontent devsite-nav"> </devsite-recommendations-sidebar> </div> </div> <devsite-content> <article class="devsite-article"> <div class="devsite-article-meta nocontent" role="navigation"> <ul class="devsite-breadcrumb-list" aria-label="Breadcrumb"> <li class="devsite-breadcrumb-item "> <a href="https://cloud.google.com/" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="Google Cloud" > Home </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://cloud.google.com/recommender/docs" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="2" track-type="globalNav" track-name="breadcrumb" track-metadata-position="2" track-metadata-eventdetail="Recommender" > Recommender </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://cloud.google.com/recommender/docs/whatis-activeassist" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="3" track-type="globalNav" track-name="breadcrumb" track-metadata-position="3" track-metadata-eventdetail="Recommender Documentation" > Documentation </a> </li> </ul> <devsite-thumb-rating position="header"> </devsite-thumb-rating> </div> <devsite-feedback position="header" project-name="Recommender Documentation" product-id="5109002" bucket="Documentation" context="" version="t-devsite-webserver-20250218-r02-rc00.467092460105212566" data-label="Send Feedback Button" track-type="feedback" track-name="sendFeedbackLink" track-metadata-position="header" class="nocontent" project-icon="https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/images/favicons/onecloud/super_cloud.png" > <button> Send feedback </button> </devsite-feedback> <h1 class="devsite-page-title" tabindex="-1"> Using Recommendations for Infrastructure as Code </h1> <devsite-feature-tooltip ack-key="AckCollectionsBookmarkTooltipDismiss" analytics-category="Site-Wide Custom Events" analytics-action-show="Callout Profile displayed" analytics-action-close="Callout Profile dismissed" analytics-label="Create Collection Callout" class="devsite-page-bookmark-tooltip nocontent" dismiss-button="true" id="devsite-collections-dropdown" dismiss-button-text="Dismiss" close-button-text="Got it"> <devsite-bookmark></devsite-bookmark> <span slot="popout-heading"> Stay organized with collections </span> <span slot="popout-contents"> Save and categorize content based on your preferences. </span> </devsite-feature-tooltip> <div class="devsite-page-title-meta"><devsite-view-release-notes></devsite-view-release-notes></div> <devsite-toc class="devsite-nav" depth="2" devsite-toc-embedded > </devsite-toc> <div class="devsite-article-body clearfix "> <div class="tutorial tutorial-lesson"> <hr class="cloud-divider"> <section id="overview"> <h2 id="overview" data-text="Overview" tabindex="-1">Overview</h2> <p><a href="/policy-intelligence">Google Cloud Policy Intelligence</a> helps enterprises understand and manage their policies to reduce their risk. By providing more visibility and automation, customers can increase security without increasing their workload.</p> <p><a href="/recommender/docs">Recommender</a> enables you to retrieve recommendations for Google Cloud resources, helping you to improve cloud security, save costs, and more. For a list of supported recommendations refer to the <a href="/recommender/docs">Recommender documentation</a>. This tutorial describes using <a href="/compute/docs/instances/apply-sizing-recommendations-for-instances">sizing recommendations for VM instances</a> and <a href="/iam/docs/recommender-overview">Identity and Access Management (IAM) recommendations</a>. Recommender uses machine learning to provide administrators with recommendations for removing unnecessary access to Google Cloud resources and resizing Compute Engine instances for more efficient resource utilization.</p> <p>Each recommendation includes a suggested action and its impact. After reviewing recommendations for the identified impacts as well as other considerations specific to your environment, you can select the recommendations that you want to apply. You can apply recommendations manually from the Google Cloud console or you can apply them programmatically by integrating them into your Infrastructure as Code (IaC) pipeline.</p> <p>IaC enables you to automate the creation of your Google Cloud resources.You must keep your IaC repository up-to-date and route changes that are made to the Google Cloud organization through it. IaC strategies in organizations generally prove to be beneficial when they are implemented with rigor and serve as the single version of truth for your cloud infrastructure. Keeping your IaC repository up-to-date is critical to prevent drifts between the version of your infrastructure that your IaC repository reflects and what you have in the organization.</p> <h3 id="recommendations" data-text="IAM recommendations" tabindex="-1">IAM recommendations</h3> <p>Amongst other leading practices, a common one is the security principle of least privilege and a careful consideration of how changes to your organization are rolled out and synchronized with your IaC repository.</p> <h3 id="sizing_recommendation_for_vms" data-text="Sizing recommendation for VMs" tabindex="-1">Sizing recommendation for VMs</h3> <p>Sizing recommendations help you lower costs by providing suggestions for resizing the machine type of your instances to more efficiently use instance resources</p> <p>This tutorial describes how to architect and build an automation pipeline to apply a Policy Intelligence recommendation programmatically. As part of this automation pipeline, you will learn how to keep your IaC repository up-to-date with the changes that you decide to make to your Google Cloud organization, based on the VM sizing and IAM policy bindings recommendation that Recommender makes available.</p> <p>This tutorial uses <a href="https://www.terraform.io/" target="external">Hashicorp Terraform</a> as the IaC tool, however the architectural patterns and components used in the described automation pipeline can be leveraged even if you are using a different IaC management tool such as <a href="/deployment-manager/docs">Deployment Manager</a>. You will need to modify the open source codebase made available with this tutorial to suit your specific IaC implementation.</p> <p>This guide is targeted at architects, product owners and developers who might be responsible for administration, security and infrastructure planning of their Google Cloud.</p> <h3 id="automation_pipeline_architecture" data-text="Automation pipeline architecture" tabindex="-1">Automation pipeline architecture</h3> <p>The following diagram shows the components you use in this automation pipeline.</p> <p><img src="/static/recommender/docs/images/iac-architecture.svg" alt="components in the automation pipeline"></p> <p>A scheduled Cloud Scheduler job runs the Recommender Parser service. The service calls the Recommender API to retrieve Recommender recommendations for the projects that you specify. It then parses these VM sizing and IAM recommendations to map them to the configuration you have in your Terraform manifests. The service updates your IaC manifests to reflect these recommendations. It generates a pull request with the changes so that you can review the updates. Once you review and merge the pull request, a Cloud Build job rolls out the changes to your infrastructure in your Google Cloud organization.</p> <p>Several ancillary Google Cloud services are used in the pipeline for the purposes of tracking processed recommendations, generating notifications on build completion and storing Terraform state. You will learn more about these services over the course of this tutorial.</p> <p>The following list describes the component purpose and access control requirements:</p> <dl> <dt>Platform Intelligence Recommenders</dt> <dd><strong>Purpose</strong>: Generate security and VM sizing recommendations</dd> <dd><p><strong>Access control</strong>: The Google Cloud service account must have the required IAM permissions to retrieve recommendations using the Recommender API.</p> <p>Review Recommender roles and permissions to select the most appropriate role applicable to the service account that you use to run the recommender-parser service.</p> <ul> <li><a href="/policy-intelligence/docs/review-apply-role-recommendations#required-permissions">Permissions for IAM recommender</a></li> <li><a href="/recommender/docs/vm-instance-rightsizing-recommender#permissions">Permissions for Compute Engine Instance sizing</a></li> </ul></dd> <dt><a href="/scheduler">Cloud Scheduler</a></dt> <dd><p><strong>Purpose</strong>: Cloud Scheduler triggers the Recommender Parser service. Cloud Scheduler enables you to setup multiple jobs invoking as many instances of the parser service as you need. Each invocation needs to pass in the following inputs</p> <ul> <li>List of projects for which recommendations should be processed</li></li> <li>Recommendation Type</li> <li>IaC repository name</li> </ul> <aside class="note"><strong>Note:</strong><span> You might want to set up multiple scheduler jobs if you have more than one IaC repository in your enterprise. Generally this is a common pattern in large enterprises.</span></aside></dd> <dd><p><strong>Access control</strong>: Create or identify a Google Cloud service account to use for the calls from Cloud Scheduler to your Recommender Parser service.</p> <p>Grant the service account the Cloud Scheduler Service Agent role so that it can run Cloud Scheduler jobs. Additionally, grant the service account the Cloud Run Invoker role since that account invokes a Cloud Run service</p> <p>See the documentation about configuring <a href="/scheduler/docs/http-target-auth">authenticated access for scheduler jobs</a> for details.</p></dd> <dt><a href="/run">Cloud Run</a> service</dt> <dd><p><strong>Purpose:</strong>: The recommender-parser service is where all the processing logic resides. It has multiple routes, each of which serve a specific purpose:</p> <ul> <li>Parsing recommendations for each recommendation type.</li> <li>Updating the status of the recommendations being processed</li> </ul></dd> <dd><p><strong>Access control</strong>: Use IAM to manage access to this service</p> <p>Additionally, assign the service to a dedicated service account. This ensures that only the service is able to invoke other services such as Firestore.</p></dd> <dt><a href="https://www.terraform.io/" class="external">Hashicorp Terraform</a> </dt> <dd><p><strong>Purpose</strong>: Terraform 0.12 is the IaC tool.</p></dd> <dd><p>A Cloud Build builder for Terraform is used to invoke Terraform commands and the Cloud Build service account is used for that purpose.</p></dd> <dt><a href="/build">Cloud Build</a></dt> <dd><p><strong>Purpose</strong>: Google Cloud Build automates the deployment of infrastructure based on the changes made to the IaC manifests per policy intelligence recommendations.</p></dd> <dd><p><strong>Access control</strong>: The Cloud Build service account must have the right set of permissions to interact with resources in your test project.</p> <p>See the documentation for <a href="/build/docs/securing-builds/set-service-account-permissions">configuring a Cloud Build service account</a>.</p></dd> <dt>GitHub</dt> <dd><p><strong>Purpose</strong>: The IaC repository uses GitHub for source control. The IaC repository in GitHub is integrated with Cloud Build. When commits are made to the master branch, a Cloud Build job is triggered to run a set of preconfigured tasks.</p></dd> <dd><p><strong>Access control:</strong> You will need to generate SSH keys to enable access to your IaC repository.</p> <p>Additionally, you need to <a href="https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line" class="external">generate a Personal Access Token</a> to push commits to GitHub.</p> <aside class="note"><strong>Note:</strong><span> SSH keys and a Personal Access Token are required when interacting with private repositories hosted in GitHub. If your repository is public (not recommended) this step does not apply to you.</span></aside></dd> <dt><a href="/firestore">Firestore</a></dt> <dd><p>Firestore is a fully managed, scalable NoSQL document database that is used in this architecture to persist information related to the Recommendation IDs that are parsed by the Recommender Parser service, along with the corresponding details pertinent to Git commits.</p> <p>The details that are persisted in Firestore play an integral role in the feedback loop that is part of the end to end pipeline. After picking up a recommendation generated by the Recommender API and prior to processing the recommendation, the service marks the recommendation's state to <code translate="no" dir="ltr">CLAIMED</code>. After the recommendation is successfully applied, the service queries the database to retrieve the recommendation IDs that have been successfully applied by the Cloud Build job and changes the recommendation state to <code translate="no" dir="ltr">SUCCEEDED</code>. If the Cloud Build Job fails, the recommendation state is changed to <code translate="no" dir="ltr">FAILED</code>.</p></dd> <dd><p><strong>Access control:</strong> Refer to <a href="/firestore/docs/security/iam#roles">Firestore roles</a> for details. The recommender-parser service reads data from Firestore and needs the roles/datastore.user role to do so.</td></p></dd> <dt><a href="/pubsub">Pub/Sub</a></dt> <dd><p><strong>Purpose:</strong> Cloud Build publishes messages on a <a href="/pubsub">Pub/Sub</a> topic when your build's state changes, such as when your build is created, when your build transitions to a working state, and when your build completes.</p> <p>The Pub/Sub topic to which Cloud Build publishes messages is called cloud-builds, and it is automatically created for you when you enable the Cloud Build API in your project.</p></dd> <dd><p><strong>Access control</strong>: Push subscriptions can be configured to provide an authentication header to allow service to authorize the request. Refer to <a href="/pubsub/docs/push">Using Push Subscriptions</a> for more details.</p></dd> </dl> </section> <section id="objectives"> <h2 id="objectives" data-text="Objectives" tabindex="-1">Objectives</h2> <ul> <li>Build an automation pipeline to <ul> <li>Proactively monitor platform Policy Intelligence recommendations</li> <li>Parse recommendations and apply updates to an existing IaC repository</li> </ul></li> <li>Learn how you can use a suite of Google Cloud services, <a href="https://www.terraform.io/" target="external">Hashicorp Terraform</a> and <a href="https://github.com/" target="github">GitHub</a> to build this pipeline.</li> <li>Understand the assumptions and best practices you need to keep in mind to build this pipeline</li> <li>Test the pipeline</li> </ul> </section> <section id="costs"> <h2 id="costs" data-text="Costs" tabindex="-1">Costs</h2> <p> In this document, you use the following billable components of Google Cloud: </p> <ul> <li>Cloud Run</li> <li>Cloud Build</li> <li>Compute Engine</li> <li>Cloud Storage</li> <li>Firestore</li> <li>Pub/Sub</li> <li>Cloud Scheduler</li> <li>Recommender</li> </ul> <p> To generate a cost estimate based on your projected usage, use the <a href="/products/calculator" track-type="commonIncludes" track-name="pricingCalculator">pricing calculator</a>. <cloudx-free-trial-eligible-content> <slot slot="eligible"> New Google Cloud users might be eligible for a <a href="/free" track-type="freeTrial" track-name="consoleLink" track-metadata-position="prerequisites" track-metadata-end-goal="signUp" target="_blank">free trial</a>. </slot> <slot slot="ineligible"> </slot> </cloudx-free-trial-eligible-content> </p> </section> <section id="prerequisites"> <h2 id="before-you-begin" data-text="Before you begin" tabindex="-1">Before you begin</h2> <p>This tutorial assumes that you have a <a href="https://github.com/" target="github" track-type="article" track-name="gitHubLink" track-metadata-position="body">GitHub</a> account, and are familiar with <a href="https://git-scm.com/" target="external">Git</a>, <a href="https://nodejs.org/en/" target="external">Node.js</a>, <a href="https://www.terraform.io/" target="external">Terraform</a> and <a href="https://www.docker.com/" target="external">Docker</a>.</p> <h3 id="release_notes_and_assumptions" data-text="Release Notes and Assumptions" tabindex="-1">Release Notes and Assumptions</h3> <p>There is a lot of variability in how IaC tools and manifests are used.</p> <p>Review the following information to determine how this tutorial can fit your IaC pipeline and what kinds of changes might be required.</p> <ul> <li>This pipeline uses Terraform <em>ver</em>. 0.12. Significant changes in <a href="https://www.terraform.io/docs/configuration/syntax.html" target="external">HCL</a> configuration syntax or changes to the structure of the Terraform state file might introduce breaking issues.</li> <li>This pipeline assumes that the IaC directory structures are not nested and that one IaC repository manages resources in one or more Google Cloud projects.</li> <li>Terraform variables passed in as environment variables, command line arguments are not supported. The prototype assumes declarative configuration of Terraform variables in a tfvars file.</li> <li>Recommender generates IAM recommendations when a subset of permissions for a role have not been used for 60 days and VM sizing recommendations follow a similar pattern. For the purposes of this tutorial, sample recommendation payloads have been provided that can be used to test the pipeline.</li> <li>Loops within Terraform are not supported in this release</li> <li>Terraform Modules are not supported. The codebase is open source and it is assumed that you will make any necessary specific enhancements to the parsing flow to suit your directory structure and usage of modules.</li> </ul> <p>The current version of the open source recommender parser service is aligned to the following known limitations of <a href="/iam/docs/recommender-overview">IAM recommendations</a>:</p> <ul> <li>Recommendations can only be made for IAM policy bindings that are: <ul> <li>At the project level</li> <li>Associated with <a href="/iam/docs/overview#google_account">user accounts</a> and <a href="/iam/docs/service-account-types#user-managed">user-managed service accounts</a></li> </ul></li> <li>IAM recommendations support <a href="/iam/docs/understanding-roles#basic">basic roles</a> and <a href="/iam/docs/understanding-roles#predefined_roles">predefined roles</a> only. <a href="/iam/docs/understanding-custom-roles">Custom roles</a> and <a href="/iam/docs/conditions-overview">conditional bindings</a> cannot be evaluated or recommended.</li> <li>Recommended roles only contain a subset of the current role's permissions. No new permissions are introduced by a recommended role.</li> </ul> <h3 id="prerequisites" data-text="Prerequisites" tabindex="-1">Prerequisites</h3> <ol> <li>Select or create two Google Cloud projects. <p> <a href="https://console.cloud.google.com/projectselector2/home/dashboard" target="console" track-type="commonIncludes" track-name="consoleLink" track-metadata-end-goal="createProject" class="button button-primary">Go to the project selector page</a> </p> <ul> <li>A <strong>build</strong> project that hosts and runs the automation pipeline.</li> <li>A <strong>test</strong> project that hosts Google Cloud resources used to test the automation pipeline.</li> </ul> </li> <li> <p> <a href="/billing/docs/how-to/verify-billing-enabled#confirm_billing_is_enabled_on_a_project" target="_blank" track-type="commonIncludes" track-name="supportLink" track-metadata-end-goal="enableBilling" >Make sure that billing is enabled for your Google Cloud project</a>. </p> </li> <li>In the <strong>test</strong> project, enable the Recommender and Compute Engine API. <p> </p><p><a href="https://console.cloud.google.com/flows/enableapi?apiid=recommender.googleapis.com,compute" target="console" track-type="commonIncludes" track-name="consoleLink" track-metadata-end-goal="enableAPI" class="button button-primary">Enable the APIs</a></p> <style> .henhouse-text { font-size:85%; padding:2px 4px; line-height:1; } </style> </li> <li>In the <strong>build</strong> project, enable the Cloud Run, Firestore, Pub/Sub and Cloud Scheduler, IAM and CloudResourceManager APIs. <p> </p><p><a href="https://console.cloud.google.com/flows/enableapi?apiid=run.googleapis.com,pubsub.googleapis.com,cloudbuild.googleapis.com,cloudscheduler.googleapis.com,firestore.googleapis.com,cloudresourcemanager.googleapis.com,iam" target="console" track-type="commonIncludes" track-name="consoleLink" track-metadata-end-goal="enableAPI" class="button button-primary">Enable the APIs</a></p> <style> .henhouse-text { font-size:85%; padding:2px 4px; line-height:1; } </style> </li> </ol> </section> <div id="tutorial-content"> <section class="tutorial-content"> <p>When you finish this tutorial, you can avoid continued billing by deleting the resources you created. See <a href="#heading=h.mlrdlgcohh7k">Cleaning up</a> for more detail.</p> <h2 id="set_up_your_environment" data-text="Set up your environment" tabindex="-1">Set up your environment</h2> <ol> <li>In Google Cloud console, select your <code translate="no" dir="ltr">build</code> project.</li> <li><p>In the Google Cloud console, go to Cloud Shell. <p><a href="https://console.cloud.google.com/?cloudshell=true" target="console" track-type="commonIncludes" track-name="consoleLink" track-metadata-end-goal="launchCloudShell" class="button button-primary">Go to Cloud Shell</a></p> <p> At the bottom of the Google Cloud console, a <a href="/shell/docs/features">Cloud Shell</a> session opens and displays a command-line prompt. Cloud Shell is a shell environment with the <a href="/sdk/gcloud">Google Cloud CLI</a> already installed, and with values already set for your current project. It can take a few seconds for the session to initialize. </p></p> <p>Use Cloud Shell for all of the terminal commands in this tutorial.</p></li> <li><p>Create an environment variable to hold the project number for your <code translate="no" dir="ltr">build</code> project using the command below:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr"><span class="devsite-syntax-nb">export</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">BUILD_PROJECT_ID</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-nv">$DEVSHELL_PROJECT_ID</span> </code></pre></devsite-code></li> <li><p>Create an environment variable to hold the project number for your <code translate="no" dir="ltr">test</code> project . Copy the test project ID manually and replace <var translate="no">PROJECT-ID</var> with it,</p> <div></div><devsite-code><pre class="devsite-click-to-copy notranslate" dir="ltr" is-upgraded syntax="Bash"><span class="devsite-syntax-nb">export</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">TEST_PROJECT_ID</span><span class="devsite-syntax-o">=</span><var translate="no">PROJECT-ID</var></pre></devsite-code></li> <li><p>You assign default settings for values that are used throughout the tutorial, such as <a href="/compute/docs/regions-zones">region and zone</a>. In this tutorial, you use us-central1 as the default region and us-central1-b as the default zone.</p></li> <li><p>Set the default region and zone for this tutorial by running the following command:.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>config<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nb">set</span><span class="devsite-syntax-w"> </span>compute/zone<span class="devsite-syntax-w"> </span>us-central1-b<span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span> gcloud<span class="devsite-syntax-w"> </span>config<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nb">set</span><span class="devsite-syntax-w"> </span>compute/zone<span class="devsite-syntax-w"> </span>us-central1-b<span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span> </code></pre></devsite-code></li> <li><p>Set your <code translate="no" dir="ltr">build</code> project as the default project:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>config<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nb">set</span><span class="devsite-syntax-w"> </span>project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span> </code></pre></devsite-code></li> <li><p>Create an environment variable called<code translate="no" dir="ltr">BUILD_PROJECT_NUMBER</code> for your<code translate="no" dir="ltr">build</code>project number</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr"><span class="devsite-syntax-nb">export</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">BUILD_PROJECT_NUMBER</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-k">$(</span>gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>describe<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$DEVSHELL_PROJECT_ID</span><span class="devsite-syntax-w"> </span>--format<span class="devsite-syntax-o">=</span><span class="devsite-syntax-s1">'value(projectNumber)'</span><span class="devsite-syntax-k">)</span> </code></pre></devsite-code></li> <li><p>Clone the <a href="https://github.com/GoogleCloudPlatform/recommender-iac-pipeline-nodejs-tutorial" class="external">GitHub repository</a> for this tutorial:</p> <aside class="note"><strong>Note:</strong><span> Execute all the commands in this tutorial in Cloud Shell unless specified otherwise.</span></aside></li> </ol> <h2 id="create_bucket_for_terraform_state" data-text="Create Bucket for Terraform State" tabindex="-1">Create Bucket for Terraform State</h2> <p>Create a Cloud Storage bucket in your build project to store the Terraform state file.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>storage<span class="devsite-syntax-w"> </span>buckets<span class="devsite-syntax-w"> </span>create<span class="devsite-syntax-w"> </span>gs://recommender-tf-state-<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-o">=</span><span class="devsite-syntax-si">${</span><span class="devsite-syntax-nv">BUILD_PROJECT_ID</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-w"> </span>--location<span class="devsite-syntax-o">=</span>us-central1 </code></pre></devsite-code> <h2 id="create_a_github_repository" data-text="Create a GitHub repository" tabindex="-1">Create a GitHub repository</h2> <p>Create a GitHub repository to serve as the sample IaC repository</p> <ol> <li><p>Create a new private GitHub repository. This <var translate="no">IAC-REPO-NAME</var> repository serves as your IaC repository for the purposes of this tutorial</p></li> <li><p>In the following setps, you will push the files in the <code translate="no" dir="ltr">sample-iac</code> sub-directory of the cloned repository to your GitHub account.</p> <ol> <li><p>In Cloud Shell, copy the <code translate="no" dir="ltr">sample-iac</code> directory to your home directory. You will use this directory to create a new local repository and push that to GitHub.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">cp<span class="devsite-syntax-w"> </span>-r<span class="devsite-syntax-w"> </span>recommender-iac-pipeline-nodejs-tutorial/sample-iac<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$HOME</span> </code></pre></devsite-code></li> <li><p>Navigate to the new directory</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr"><span class="devsite-syntax-nb">cd</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$HOME</span>/sample-iac </code></pre></devsite-code></li> <li><p>Initialize the repository in your local machine.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">git<span class="devsite-syntax-w"> </span>init </code></pre></devsite-code></li> <li><p>Add <var translate="no">IAC-REPO-NAME</var> as the remote repository, replace <var translate="no">IAC-REPO-NAME</var> and <var translate="no">GITHUB-ACCOUNT</var> with appropriate values</p> <div></div><devsite-code><pre class="devsite-click-to-copy notranslate" dir="ltr" is-upgraded syntax="Bash">git<span class="devsite-syntax-w"> </span>remote<span class="devsite-syntax-w"> </span>add<span class="devsite-syntax-w"> </span>origin<span class="devsite-syntax-w"> </span>https://github.com/<var translate="no">GITHUB-ACCOUNT</var>/<var translate="no">IAC-REPO-NAME</var></pre></devsite-code></li> <li><p>Replace the placeholders in the files in this repository with your<code translate="no" dir="ltr">test</code>project ID and the Terraform Cloud Storage bucket name.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">sed<span class="devsite-syntax-w"> </span>-i<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"s|__PROJECT_ID__|</span><span class="devsite-syntax-si">${</span><span class="devsite-syntax-nv">TEST_PROJECT_ID</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-s2">|g"</span><span class="devsite-syntax-w"> </span>./terraform.tfvars sed<span class="devsite-syntax-w"> </span>-i<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"s|__STATE_BUCKET_NAME__|recommender-tf-state-</span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-s2">|g"</span><span class="devsite-syntax-w"> </span>./backend.tf </code></pre></devsite-code></li> <li><p>Add, commit, and push to GitHub.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">git<span class="devsite-syntax-w"> </span>add<span class="devsite-syntax-w"> </span>. git<span class="devsite-syntax-w"> </span>commit<span class="devsite-syntax-w"> </span>-m<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"First Commit"</span> git<span class="devsite-syntax-w"> </span>push<span class="devsite-syntax-w"> </span>origin<span class="devsite-syntax-w"> </span>master </code></pre></devsite-code></li> <li><p>Sign in to your GitHub account when prompted.</p></li> </ol></li> </ol> <h2 id="generate_ssh_keys_for_your_repository" data-text="Generate SSH keys for your repository" tabindex="-1">Generate SSH keys for your repository</h2> <p>Set up SSH key authentication with your IaC repository in GitHub and upload the keys to Cloud Storage.</p> <ol> <li><p>Generate SSH keys for your GitHub repository.</p> <ol> <li><p>Generate an SSH key pair. Replace <var translate="no">your_email@example.com</var> with your GitHub email address. In Cloud Shell:</p> <div></div><devsite-code><pre class="devsite-click-to-copy notranslate" dir="ltr" is-upgraded syntax="Bash">ssh-keygen<span class="devsite-syntax-w"> </span>-t<span class="devsite-syntax-w"> </span>rsa<span class="devsite-syntax-w"> </span>-b<span class="devsite-syntax-w"> </span><span class="devsite-syntax-m">4096</span><span class="devsite-syntax-w"> </span>-m<span class="devsite-syntax-w"> </span>PEM<span class="devsite-syntax-w"> </span>-C<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"<var translate="no">your_email@example.com</var>"</span></pre></devsite-code></li> <li><p>When you're prompted to "Enter a file in which to save the key," press <strong>Enter</strong>. This accepts the default file location.</p></li> <li><p>At the prompt to enter a passphrase, press <strong>Enter</strong>.</p></li> </ol></li> <li><p>Make note of the directory <var translate="no">SSH-KEYS-DIR</var> that you save the downloaded SSH keys in. By default the location is<code translate="no" dir="ltr">$HOME/.ssh/</code></p></li> <li><p>Copy the SSH public key that you generated to your GitHub repository as a <a href="https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys" target="github" track-type="article" track-name="gitHubLink" track-metadata-position="body">Deploy Key</a>.</p> <ol> <li><p>Copy the SSH public key that you generated in Cloud Shell. Replace <var translate="no">SSH-KEYS-DIR</var> with your directory path.</p> <div></div><devsite-code><pre class="devsite-click-to-copy notranslate" dir="ltr" is-upgraded syntax="Bash">cat<span class="devsite-syntax-w"> </span><var translate="no">SSH-KEYS-DIR</var>/id_rsa.pub</pre></devsite-code></li> <li><p>In your GitHub account, navigate to the <var translate="no">IAC-REPO-NAME</var> repository</p></li> <li><p>Click <strong>Settings > Deploy Keys</strong>.</p></li> <li><p>Click <strong>Add Deploy Key</strong> and paste in the SSH public key you copied. Choose a <strong>Title</strong> for the key.</p></li> <li><p>Select the check box "<strong>Allow write access</strong>"</p></li> <li><p>Click <strong>Save</strong>.</p></li> </ol></li> <li><p>Navigate back to your Cloud Shell session</p></li> <li><p>Create the<code translate="no" dir="ltr">known_hosts</code> file for GitHub. In your Cloud Shell session, run the command:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">ssh-keyscan<span class="devsite-syntax-w"> </span>github.com<span class="devsite-syntax-w"> >> </span>~/.ssh/known_hosts </code></pre></devsite-code></li> <li><p>Create a Cloud Storage bucket in your<code translate="no" dir="ltr">build</code> project and upload your SSH keys and <code translate="no" dir="ltr">known_hosts</code> file to it. Replace <var translate="no">SSH-KEYS-DIR</var> with the path to the directory where you generated the SSH keys.</p> <div></div><devsite-code><pre class="devsite-click-to-copy notranslate" dir="ltr" is-upgraded syntax="Bash">gcloud<span class="devsite-syntax-w"> </span>storage<span class="devsite-syntax-w"> </span>buckets<span class="devsite-syntax-w"> </span>create<span class="devsite-syntax-w"> </span>gs://github-keys-<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-o">=</span><span class="devsite-syntax-si">${</span><span class="devsite-syntax-nv">BUILD_PROJECT_ID</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-w"> </span>--location<span class="devsite-syntax-o">=</span>us-central1 gcloud<span class="devsite-syntax-w"> </span>storage<span class="devsite-syntax-w"> </span>cp<span class="devsite-syntax-w"> </span><var translate="no">SSH-KEYS-DIR</var>/id_rsa*<span class="devsite-syntax-w"> </span>gs://github-keys-<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span> gcloud<span class="devsite-syntax-w"> </span>storage<span class="devsite-syntax-w"> </span>cp<span class="devsite-syntax-w"> </span><var translate="no">SSH-KEYS-DIR</var>/known_hosts<span class="devsite-syntax-w"> </span>gs://github-keys-<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span></pre></devsite-code></li> <li><p>Generate a <strong>Personal Access Token</strong> for GitHub. This token is used when performing Git operations using API calls that the recommender-parser service makes to generate pull requests, check-in updated IaC manifests.</p> <ol> <li><p>In your GitHub account, in the upper-right corner of any page, click your profile photo, then click <strong>Settings</strong>.</p></li> <li><p>In the left sidebar, click <strong>Developer settings</strong>.</p></li> <li><p>In the left sidebar, click <strong>Personal access tokens</strong></p></li> <li><p>Click Generate new token.</p></li> <li><p>Give your token a descriptive name.</p></li> <li><p>Select the scopes as <strong>repo</strong>.</p></li> <li><p>Click <strong>Generate token</strong>.</p></li> <li><p>Copy the token to your clipboard.</p></li> <li><p>In your Cloud Shell session, create an environment variable.</p> <div></div><devsite-code><pre class="devsite-click-to-copy notranslate" dir="ltr" is-upgraded syntax="Bash"><span class="devsite-syntax-nb">export</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">GITHUB_PAT</span><span class="devsite-syntax-o">=</span><var translate="no">personal-access-token-you-copied</var></pre></devsite-code></li> </ol></li> </ol> <h2 id="set_up" data-text="Set up Cloud Build" tabindex="-1">Set up Cloud Build</h2> <ol> <li><p>Connect your <var translate="no">IAC-REPO-NAME</var> Git repository to integrate with Cloud Build.</p> <ol> <li>Go to the <a href="https://github.com/marketplace/google-cloud-build" target="github" track-type="article" track-name="gitHubLink" track-metadata-position="body">Cloud Build App page</a> in the GitHub Marketplace.</li> <li>Scroll down and click <strong>Setup with Google Cloud Build</strong> at the bottom of the page.</li> <li>If prompted, <strong>Sign in to GitHub</strong>.</li> <li>Select <strong>Only select repositories</strong>. Use the <strong>Select repositories</strong> drop-down list to only enable access to your <var translate="no">IAC-REPO-NAME</var> in the Cloud Build app.</li> <li>Click <strong>Install</strong>.</li> <li><p>Sign in to Google Cloud.</p> <p>The Authorization page is displayed where you are asked to authorize the <strong>Google Cloud Build</strong> app to connect to Google Cloud.</p></li> <li><p>Click <strong>Authorize Google Cloud Build by GoogleCloudBuild</strong>. You are redirected to the Google Cloud console.</p></li> <li><p>Select your Google Cloud project.</p></li> <li><p>Enable the consent checkbox and click <strong>Next</strong>.</p></li> <li><p>In the <strong>Select repository</strong> page that appears, select the <var translate="no">IAC-REPO-NAME</var> GitHub repo</p></li> <li><p>Click <strong>Connect repository</strong>.</p></li> <li><p>Click <strong>Create a Trigger</strong>. This creates a trigger definition for you.</p></li> <li><p>Click <strong>Create</strong> to save your build trigger.</p></li> </ol> <p>For more information, see <a href="/build/docs/run-builds-on-github#installing_the_google_cloud_build_app">Running builds on GitHub</a>.</p></li> <li><p>The directory that you copied has a <code translate="no" dir="ltr">cloudbuild.yaml</code> file. This configuration file outlines the steps that a Cloud Build job executes when triggered.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="YAML"><code translate="no" dir="ltr"><span class="devsite-syntax-nt">steps</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p devsite-syntax-p-Indicator">-</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nt">name</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain">hashicorp/terraform:0.12.0</span> <span class="devsite-syntax-w"> </span><span class="devsite-syntax-nt">args</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p devsite-syntax-p-Indicator">[</span><span class="devsite-syntax-s">'init'</span><span class="devsite-syntax-p devsite-syntax-p-Indicator">]</span> <span class="devsite-syntax-p devsite-syntax-p-Indicator">-</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nt">name</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain">hashicorp/terraform:0.12.0</span> <span class="devsite-syntax-w"> </span><span class="devsite-syntax-nt">args</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p devsite-syntax-p-Indicator">[</span><span class="devsite-syntax-s">'apply'</span><span class="devsite-syntax-p devsite-syntax-p-Indicator">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s">'-auto-approve'</span><span class="devsite-syntax-p devsite-syntax-p-Indicator">]</span> </code></pre></devsite-code></li> <li><p>Add permissions to your Cloud Build service account to allow it to create service accounts, associate roles, and virtual machines (Compute Engine instances) in the test project</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-w"> </span>serviceAccount:<span class="devsite-syntax-nv">$BUILD_PROJECT_NUMBER</span>@cloudbuild.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-w"> </span>roles/compute.admin<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span> gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-w"> </span>serviceAccount:<span class="devsite-syntax-nv">$BUILD_PROJECT_NUMBER</span>@cloudbuild.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-w"> </span>roles/iam.serviceAccountAdmin<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span> gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> --member<span class="devsite-syntax-w"> </span>serviceAccount:<span class="devsite-syntax-nv">$BUILD_PROJECT_NUMBER</span>@cloudbuild.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> --role<span class="devsite-syntax-w"> </span>roles/iam.securityAdmin<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> --project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span> </code></pre></devsite-code></li> <li><p><a href="https://console.cloud.google.com/cloud-build/triggers" target="console" track-name="consoleLink" track-metadata-position="body">Open the Build Triggers page</a> in the Google Cloud console.</p></li> <li><p>Select <code translate="no" dir="ltr">build</code> project, click <strong>Open</strong>.</p></li> <li><p>Update the trigger's definition:</p> <ol> <li>Click <span class="material-icons" aria-hidden="true" translate="no">more_vert</span> menu and then click <strong>Edit</strong>.</li> <li>For <strong>Configuration</strong>, select the <strong>Cloud Build configuration file (yaml or json)</strong> option and type in <code translate="no" dir="ltr">cloudbuild.yaml</code> in the text field.</li> <li>Click <strong>Save</strong>.</li> </ol></li> <li><p>To manually test the build trigger, click <strong>Run</strong> on your trigger's entry in the triggers list.</p></li> <li><p>Verify that a Compute Engine instance called <code translate="no" dir="ltr">tf-compute-1</code> and a service account called <code translate="no" dir="ltr">Terraform Recommender Test</code> are created in your test project by the Cloud Build job you ran in the previous step</p></li> </ol> <aside class="note"><strong>Note:</strong><span> You might need to wait a few moments for the Cloud Build job to complete before verifying the creation of resources in your test project.</span></aside> <h2 id="deploy_the_recommender-parser_service" data-text="Deploy the recommender-parser Cloud Run service" tabindex="-1">Deploy the recommender-parser Cloud Run service</h2> <ol> <li><p>In Cloud Shell, Change directories to the directory created by cloning the repository</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr"><span class="devsite-syntax-nb">cd</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$HOME</span>/recommender-iac-pipeline-nodejs-tutorial/parser-service </code></pre></devsite-code></li> <li><p>Configure Google Cloud to use a default region for Cloud Run services. In this tutorial, you use the us-central1 region but you can choose a different supported region if you prefer.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>config<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nb">set</span><span class="devsite-syntax-w"> </span>run/region<span class="devsite-syntax-w"> </span>us-central1 </code></pre></devsite-code></li> <li><p>The <code translate="no" dir="ltr">parser-service</code>directory has a stub sub-directory which has a few sample payload JSONs for you to test the recommender-parser service with. Run the following sed commands to replace the <strong>PROJECT_ID</strong> placeholders in these JSONs with your test project ID.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">sed<span class="devsite-syntax-w"> </span>-i<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"s|__PROJECT_ID__|</span><span class="devsite-syntax-si">${</span><span class="devsite-syntax-nv">TEST_PROJECT_ID</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-s2">|g"</span><span class="devsite-syntax-w"> </span>./stub/iam.json sed<span class="devsite-syntax-w"> </span>-i<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"s|__PROJECT_ID__|</span><span class="devsite-syntax-si">${</span><span class="devsite-syntax-nv">TEST_PROJECT_ID</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-s2">|g"</span><span class="devsite-syntax-w"> </span>./stub/vm.json </code></pre></devsite-code></li> <li><p>Run the following command to create an environment variable for your Docker image.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="GDScript"><code translate="no" dir="ltr"><span class="devsite-syntax-k">export</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-n">IMAGE</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-n">gcr</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">io</span><span class="devsite-syntax-o">/$</span><span class="devsite-syntax-n">BUILD_PROJECT_ID</span><span class="devsite-syntax-o">/</span><span class="devsite-syntax-n">recommender</span><span class="devsite-syntax-o">-</span><span class="devsite-syntax-n">parser</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-mf">1.0</span> </code></pre></devsite-code></li> <li><p>Build the image and upload to <a href="/container-registry">Container Registry</a></p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>builds<span class="devsite-syntax-w"> </span>submit<span class="devsite-syntax-w"> </span>--tag<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$IMAGE</span><span class="devsite-syntax-w"> </span>. </code></pre></devsite-code></li> <li><p>Create a service account for the recommender-parser service to interact with other Google Cloud services in the pipeline. It is a good practice to grant granular permissions to your Cloud Run services, refer to <a href="/run/docs/securing/service-identity">Cloud Run service identity</a> for more details.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>beta<span class="devsite-syntax-w"> </span>iam<span class="devsite-syntax-w"> </span>service-accounts<span class="devsite-syntax-w"> </span>create<span class="devsite-syntax-w"> </span>recommender-parser-sa<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--description<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"Service account that the recommender-parser service uses to invoke other Google Cloud services"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--display-name<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"recommender-parser-sa"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span> </code></pre></devsite-code></li> <li><p>The recommender-parser service needs to access the GitHub SSH keys and Terraform state you uploaded to Cloud Storage buckets created earlier. Add the service account as a member to the Cloud Storage bucket.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>storage<span class="devsite-syntax-w"> </span>buckets<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span>gs://github-keys-<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-o">=</span>serviceAccount:recommender-parser-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-o">=</span>roles/storage.objectUser gcloud<span class="devsite-syntax-w"> </span>storage<span class="devsite-syntax-w"> </span>buckets<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span>gs://recommender-tf-state-<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-o">=</span>serviceAccount:recommender-parser-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-o">=</span>roles/storage.objectUser </code></pre></devsite-code></li> <li><p>Give the recommender-parser service's service account access to Firestore, Recommender, and the Service Usage API.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-w"> </span>serviceAccount:recommender-parser-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-w"> </span>roles/datastore.user gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-w"> </span>serviceAccount:recommender-parser-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-w"> </span>roles/recommender.iamAdmin gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-w"> </span>serviceAccount:recommender-parser-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-w"> </span>roles/recommender.iamViewer gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-w"> </span>serviceAccount:recommender-parser-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-w"> </span>roles/recommender.computeAdmin gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-w"> </span>serviceAccount:recommender-parser-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-w"> </span>roles/serviceusage.serviceUsageConsumer </code></pre></devsite-code></li> <li><p>Deploy the Cloud Run service, which is called <em>recommender-parser</em>, by running the command. Replace <var translate="no">GITHUB-ACCOUNT</var> with your GitHub account username, not email. Accept any system prompts.</p> <div></div><devsite-code><pre class="devsite-click-to-copy notranslate" dir="ltr" is-upgraded syntax="Bash">gcloud<span class="devsite-syntax-w"> </span>run<span class="devsite-syntax-w"> </span>deploy<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--image<span class="devsite-syntax-o">=</span><span class="devsite-syntax-si">${</span><span class="devsite-syntax-nv">IMAGE</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--no-allow-unauthenticated<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--region<span class="devsite-syntax-w"> </span>us-central1<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--platform<span class="devsite-syntax-w"> </span>managed<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--service-account<span class="devsite-syntax-w"> </span>recommender-parser-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--set-env-vars<span class="devsite-syntax-o">=</span><span class="devsite-syntax-s2">"GITHUB_ACCOUNT=github.com:<var translate="no">GITHUB-ACCOUNT</var>,GITHUB_PAT=</span><span class="devsite-syntax-si">${</span><span class="devsite-syntax-nv">GITHUB_PAT</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-s2">,SSH_KEYS_BUCKET=github-keys-</span><span class="devsite-syntax-si">${</span><span class="devsite-syntax-nv">BUILD_PROJECT_ID</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-s2">,TERRAFORM_STATE_BUCKET=recommender-tf-state-</span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-s2">"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>recommender-parser</pre></devsite-code></li> </ol> <h2 id="set_up" data-text="Set up Firestore" tabindex="-1">Set up Firestore</h2> <ol> <li>In Google Cloud console, in your <code translate="no" dir="ltr">build</code> project, navigate to the <a href="https://console.cloud.google.com/firestore/data" target="console" track-type="article" track-name="consoleLink" track-metadata-position="body">Firestore page</a>.</li> <li>When prompted for mode selection, click <strong>Select Native Mode</strong>.</li> <li>Select<code translate="no" dir="ltr">us-east1</code> as the default <strong>location</strong>.</li> <li>Click <strong>Create Database</strong>.</li> </ol> <p>The<code translate="no" dir="ltr">recommender-parser</code> service writes documents to this database for the following purposes:</p> <ul> <li>To keep track of the recommendations it has retrieved from the Recommender API</li> <li>Call the Recommender API once the recommendations are processed to update the status of each processed recommendation to <code translate="no" dir="ltr">SUCCEEDED</code> or <code translate="no" dir="ltr">FAILED</code> as appropriate. This is a key step that makes the pipeline idempotent by ensuring that recommendations are not processed incompletely or multiple times.</li> </ul> <h2 id="set_up_a_job" data-text="Set up a Cloud Scheduler job" tabindex="-1">Set up a Cloud Scheduler job</h2> <ol> <li><p>Create a service account that Cloud Scheduler jobs use to run the recommender-parser service.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>beta<span class="devsite-syntax-w"> </span>iam<span class="devsite-syntax-w"> </span>service-accounts<span class="devsite-syntax-w"> </span>create<span class="devsite-syntax-w"> </span>recommender-scheduler-sa<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--description<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"Service Account used by Cloud Scheduler to invoke the recommender-parser service"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--display-name<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"recommender-scheduler-sa"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span> </code></pre></devsite-code></li> <li><p>Give the service account run/invoker role to be able to invoke the Cloud Run service.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>beta<span class="devsite-syntax-w"> </span>run<span class="devsite-syntax-w"> </span>services<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span>recommender-parser<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> --member<span class="devsite-syntax-o">=</span>serviceAccount:recommender-scheduler-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> --role<span class="devsite-syntax-o">=</span>roles/run.invoker<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> --region<span class="devsite-syntax-o">=</span>us-central1 </code></pre></devsite-code></li> <li><p>Get your recommender-service URL:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>beta<span class="devsite-syntax-w"> </span>run<span class="devsite-syntax-w"> </span>services<span class="devsite-syntax-w"> </span>list<span class="devsite-syntax-w"> </span>--platform<span class="devsite-syntax-w"> </span>managed<span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span> </code></pre></devsite-code> <p>Your Cloud Scheduler job invokes the recommender-parser service's /recommendation/iam route to parse IAM recommendations and the /recommender/vm route to parse VM sizing recommendations.</p></li> <li><p>Create a variable for the endpoint that Cloud Scheduler jobs invoke. Replace <var translate="no">RECOMMENDER-SERVICE-URL</var> with the recommender-service URL you copied in the previous step.</p> <div></div><devsite-code><pre class="devsite-click-to-copy notranslate" dir="ltr" is-upgraded syntax="Bash"><span class="devsite-syntax-nb">export</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">RECOMMENDER_ROUTE_TO_INVOKE_IAM</span><span class="devsite-syntax-o">=</span><var translate="no">RECOMMENDER-SERVICE-URL</var>/recommendation/iam</pre></devsite-code> <p>You URL should look like this sample URL after appending the route information:</p> <div></div><devsite-code><pre translate="no" dir="ltr" is-upgraded> <var translate="no">RECOMMENDER-SERVICE-URL</var>/recommendation/iam </pre></devsite-code></li> <li><p>Create a Cloud Scheduler job called <code translate="no" dir="ltr">recommender-iam-scheduler.</code></p> <ul> <li>Change the selected time-zone based on your location.</li> <li>Replace <var translate="no">IAC-REPO-NAME</var> with the name of the GitHub repository you created.</li> </ul> <p>The message body takes three inputs and you must construct it as outlined below:</p> <ul> <li><p><code translate="no" dir="ltr">repo</code>: This is the name of your GitHub repository <var translate="no">IAC-REPO-NAME</var> that you created in <a href="#create_a_github_repository">Create a GitHub repository</a>.</p></li> <li><p><code translate="no" dir="ltr">projects</code>: A list / array of Google Cloud projects IDs that this IaC GitHub repository maps to. In this tutorial, it is your <code translate="no" dir="ltr">test</code> project.</p></li> <li><p><code translate="no" dir="ltr">stub</code>: Recommender generates IAM recommendations when a subset of permissions for a role have not been used for 60 days and VM sizing recommendations follow a similar pattern. For the purposes of testing this pipeline on demand, <code translate="no" dir="ltr">stub</code> can be passed in as <code translate="no" dir="ltr">true</code> so that the pipeline is tested using the sample Recommender payloads provided in the repository that you cloned for this tutorial.</p></li> </ul> <div></div><devsite-code><pre class="devsite-click-to-copy notranslate" dir="ltr" is-upgraded syntax="Bash">gcloud<span class="devsite-syntax-w"> </span>beta<span class="devsite-syntax-w"> </span>scheduler<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nb">jobs</span><span class="devsite-syntax-w"> </span>create<span class="devsite-syntax-w"> </span>http<span class="devsite-syntax-w"> </span>recommender-iam-scheduler<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--time-zone<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"America/Los_Angeles"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--schedule<span class="devsite-syntax-o">=</span><span class="devsite-syntax-s2">"0 */3 * * *"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--uri<span class="devsite-syntax-o">=</span><span class="devsite-syntax-nv">$RECOMMENDER_ROUTE_TO_INVOKE_IAM</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--description<span class="devsite-syntax-o">=</span><span class="devsite-syntax-s2">"Scheduler job to invoke recommendation pipeline"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--oidc-service-account-email<span class="devsite-syntax-o">=</span><span class="devsite-syntax-s2">"recommender-scheduler-sa@</span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-s2">.iam.gserviceaccount.com"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--headers<span class="devsite-syntax-o">=</span><span class="devsite-syntax-s2">"Content-Type=application/json"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--http-method<span class="devsite-syntax-o">=</span><span class="devsite-syntax-s2">"POST"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--message-body<span class="devsite-syntax-o">=</span><span class="devsite-syntax-s2">"{ \"repo\": \"<var translate="no">IAC-REPO-NAME</var>\", \"projects\": [\"</span><span class="devsite-syntax-nv">$TEST_PROJECT_ID</span><span class="devsite-syntax-s2">\"], \"location\": \"global\", \"stub\": true }"</span></pre></devsite-code></li> </ol> <aside class="note"><strong>Note:</strong><span> <code translate="no" dir="ltr">--schedule="0 */3 * * *"</code> runs the Scheduler job every 3 hours. Change it per your requirement. Also, if you need to create a scheduler job to parse VM sizing recommendations, you should append the <code translate="no" dir="ltr">your-recommender-parser</code> service URL with <code translate="no" dir="ltr">/recommendation/vm</code> and set the <code translate="no" dir="ltr">location</code> attribute in the <code translate="no" dir="ltr">--message-body</code> parameter to a valid zone.</span></aside> <h2 id="additional_steps" data-text="Additional steps" tabindex="-1">Additional steps</h2> <p>Cloud Build publishes build information to a Pub/Sub topic called cloud-builds that was automatically created when you enabled the Cloud Build API in your build project.</p> <ol> <li><p>Run the following command to verify the cloud-builds topic exists in your <code translate="no" dir="ltr">build</code> project:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>pubsub<span class="devsite-syntax-w"> </span>topics<span class="devsite-syntax-w"> </span>describe<span class="devsite-syntax-w"> </span>cloud-builds </code></pre></devsite-code> <p>If the topic exists, you will see the following output, where <var translate="no">BUILD-PROJECT-ID</var> is your build project ID:</p> <div></div><devsite-code><pre translate="no" dir="ltr" is-upgraded> name: projects/<var translate="no">BUILD-PROJECT-ID</var>/topics/cloud-builds </pre></devsite-code> <p>If you receive an error message saying the resource was not found, follow the instructions for <a href="/build/docs/subscribe-build-notifications">subscribing to build notifications</a>, to create the topic manually.</p></li> <li><p>Create a service account that Pub/Sub uses to invoke the recommender-parser service endpoint.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>beta<span class="devsite-syntax-w"> </span>iam<span class="devsite-syntax-w"> </span>service-accounts<span class="devsite-syntax-w"> </span>create<span class="devsite-syntax-w"> </span>recommender-ci-subscription-sa<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--description<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"Service Account used by Cloud Pub/Sub to push Cloud Build events to the recommender-parser service"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--display-name<span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"recommender-ci-subscription-sa"</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span> </code></pre></devsite-code></li> <li><p>The Pub/Sub service account should be associated with the roles it needs to be able to publish messages and invoke the recommender-parser service.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-w"> </span>serviceAccount:recommender-ci-subscription-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-w"> </span>roles/pubsub.publisher<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span> gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-w"> </span>serviceAccount:recommender-ci-subscription-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-w"> </span>roles/pubsub.subscriber<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span> gcloud<span class="devsite-syntax-w"> </span>projects<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-w"> </span>serviceAccount:recommender-ci-subscription-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-w"> </span>roles/run.invoker<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--project<span class="devsite-syntax-w"> </span><span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span> </code></pre></devsite-code></li> <li><p>Add the <code translate="no" dir="ltr">recommender-ci-subscription-sa</code>service account you created to the recommender-parser service as a member with the <code translate="no" dir="ltr">invoker</code> role</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">gcloud<span class="devsite-syntax-w"> </span>beta<span class="devsite-syntax-w"> </span>run<span class="devsite-syntax-w"> </span>services<span class="devsite-syntax-w"> </span>add-iam-policy-binding<span class="devsite-syntax-w"> </span>recommender-parser<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--member<span class="devsite-syntax-o">=</span>serviceAccount:recommender-ci-subscription-sa@<span class="devsite-syntax-nv">$BUILD_PROJECT_ID</span>.iam.gserviceaccount.com<span class="devsite-syntax-w"> </span><span class="devsite-syntax-se">\</span> <span class="devsite-syntax-w"> </span>--role<span class="devsite-syntax-o">=</span>roles/run.invoker<span class="devsite-syntax-w"> </span>--region<span class="devsite-syntax-o">=</span>us-central1 </code></pre></devsite-code></li> <li><p>Navigate to <a href="https://console.cloud.google.com/cloudpubsub" target="console" track-type="article" track-name="consoleLink" track-metadata-position="body">Pub/Sub</a> in Google Cloud console.</p></li> <li><p>Click the cloud-builds topic.</p></li> <li><p>Click <strong>Create Subscription</strong>.</p></li> <li><p>For Subscription ID, type <code translate="no" dir="ltr">recommender-service-build-events</code>.</p></li> <li><p>For <strong>Delivery Type</strong>, select <strong>Push</strong>.</p></li> <li><p>For <strong>Endpoint</strong>, type in your recommender-service URL appended by <code translate="no" dir="ltr">/ci</code>.</p></li> <li><p>Check <strong>Enable Authentication</strong>.</p> <ol> <li>Select the service account <code translate="no" dir="ltr">recommender-ci-subscription-sa</code>that you created.</li> <li>Click <strong>Grant</strong> in response to the prompt message.</li> </ol></li> <li><p>Select <strong>Acknowledgement deadline as 60 seconds</strong>.</p></li> <li><p>Keep rest of the defaults.</p></li> <li><p>Click <strong>Create</strong>.</p></li> </ol> <h2 id="test_the_pipeline" data-text="Test the pipeline" tabindex="-1">Test the pipeline</h2> <p>Recommender generates IAM recommendations when a subset of permissions for a role have not been used for 60 days. VM sizing recommendations follow a similar pattern. For the purposes of testing this pipeline on demand, you will use the sample recommendations JSON payloads provided in the <code translate="no" dir="ltr">stub</code> sub-directory provided in the repository you cloned for this tutorial. This enables you to test the pipeline, barring the API calls that the recommender-parser makes to the Recommender API endpoint to update the status of recommendations it has successfully applied.</p> <p>Alternatively, if you have active recommendations in your Google Cloud projects then you can test the pipeline end-to-end without needing to use stubs. The outcome outlined below is pertinent to when you are using the sample payloads for testing the pipeline. However, the steps to test this pipeline without samples remains the same.</p> <ol> <li><p>In the Google Cloud console, navigate to your test project and review the resource that were created. You should have the following:</p> <ol> <li>A Compute Engine instance called <code translate="no" dir="ltr">tf-compute-1</code> with Machine Type <code translate="no" dir="ltr">g1-small</code>.</li> <li>A service account named <code translate="no" dir="ltr">Terraform Recommender Test</code> with the role of <code translate="no" dir="ltr">editor</code> for your test project.</li> </ol></li> <li><p>In the <a href="https://console.cloud.google.com/cloudscheduler" target="console" track-type="article" track-name="consoleLink" track-metadata-position="body">Cloud Scheduler</a> console page in your <code translate="no" dir="ltr">build</code> project, click <strong>Run now</strong> for the recommender-iam-scheduler job.</p></li> <li><p>Click the job to view the logs. You can also view the recommender-parser service logs to get a detailed view of the steps being executed by the service.</p></li> <li><p>Once the service completes its run, navigate to your GitHub <var translate="no">IAC-REPO-NAME</var> repository. The <code translate="no" dir="ltr">recommender-parser</code>service would have generated a pull request for you. Review the modified IaC manifests that comprise this pull request and click <strong>Merge Pull Request</strong> if you are satisfied with the changes to your IaC manifests.</p> <aside class="warning"><strong>Warning:</strong><span> In production environments, we recommend that you enforce a robust approval workflow that includes human review of pull requests before changes are merged. The reviewers should have the knowledge to assess impacts identified in recommendations, as well as impacts specific to your infrastructure and business. Applying recommendations without proper assessment could result in unexpected changes, such as issues with system performance, poor reliability, or loss of required permissions. See the <a href="https://help.github.com/en/articles/enabling-required-reviews-for-pull-requests" target="external">GitHub documentation</a> for instructions to set up a review process.</span></aside></li> <li><p>A new commit to the master branch is created when you merge the pull request. This triggers a Cloud Build job that rolls out the modifications to the Google Cloud resources in your <code translate="no" dir="ltr">test</code> project. Allow a few moments for the Cloud Build job to complete, you can review its status in the Google Cloud console</p> <aside class="note"><strong>Note:</strong><span> Making sure that you have a functional rollback strategy in place is a best practice when setting up your DevOps pipelines. For example, the infrastructure changes rolled out by the automation pipeline that you built in this tutorial can be rolled back by reverting to a previous Git commit. You can learn more about the <a href="/recommender/docs/git%20reset">https://git-scm.com/docs/git-reset</a> and <a href="https://git-scm.com/docs/git-revert">git revert</a> commands in this Git documentation.</span></aside></li> <li><p>Once the job is complete, navigate to your test project. The sample payloads provided make the following changes to the resources in your test project.</p> <ul> <li>Terraform Test service account which earlier has a role of <code translate="no" dir="ltr">editor</code> when deployed, is changed to <code translate="no" dir="ltr">viewer</code>.</li> </ul> <aside class="note"><strong>Note:</strong><span> When you run the Cloud Scheduler service to invoke parsing VM sizing recommendations at the /recommendation/vm endpoint then the Compute Engine instance <code translate="no" dir="ltr">tf-compute-1</code> which is originally has a Machine Type of <code translate="no" dir="ltr">g1-small</code> is changed to <code translate="no" dir="ltr">f1-micro</code>.</span></aside></li> </ol> </section> </div> <section id="cleanup"> <h2 id="clean-up" data-text="Clean up" tabindex="-1">Clean up</h2> <p>To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, delete <strong>both</strong> projects that you created.</p> <p> <p> The easiest way to eliminate billing is to delete the project that you created for the tutorial. </p> <p>To delete the project: <ol> <aside class="caution"> <strong>Caution</strong>: Deleting a project has the following effects: <ul> <li> <strong>Everything in the project is deleted.</strong> If you used an existing project for the tasks in this document, when you delete it, you also delete any other work you've done in the project. </li> <li> <strong>Custom project IDs are lost.</strong> When you created this project, you might have created a custom project ID that you want to use in the future. To preserve the URLs that use the project ID, such as an <code translate="no" dir="ltr">appspot.com</code> URL, delete selected resources inside the project instead of deleting the whole project. </li> </ul> <p> If you plan to explore multiple architectures, tutorials, or quickstarts, reusing projects can help you avoid exceeding project quota limits. </p> </aside> <li> In the Google Cloud console, go to the <b>Manage resources</b> page. <p><a href="https://console.cloud.google.com/iam-admin/projects" target="console" track-type="commonIncludes" track-name="consoleLink" track-metadata-end-goal="deleteProject" class="button button-primary">Go to Manage resources</a></p> </li> <li> In the project list, select the project that you want to delete, and then click <b>Delete</b>. </li> <li> In the dialog, type the project ID, and then click <b>Shut down</b> to delete the project. </li> </ol> </p> </p> </section> <section id="whatsnext"> <h2 id="whats-next" data-text="What's next" tabindex="-1">What's next</h2> <ul> <li> Explore reference architectures, diagrams, and best practices about Google Cloud. Take a look at our <a href="/architecture" track-type="tutorial" track-name="textLink" track-metadata-position="nextSteps">Cloud Architecture Center</a>. </li> <li>Learn more about Google Cloud Policy Intelligence in the <a href="/policy-intelligence">documentation</a>.</li> </ul> </section> <section id="freetrial"> </section> </div> <devsite-hats-survey class="nocontent" hats-id="mwETRvWii0eU5NUYprb0Y9z5GVbc" listnr-id="83405"></devsite-hats-survey> </div> <devsite-thumb-rating position="footer"> </devsite-thumb-rating> <devsite-feedback position="footer" project-name="Recommender Documentation" product-id="5109002" bucket="Documentation" context="" version="t-devsite-webserver-20250218-r02-rc00.467092460105212566" data-label="Send Feedback Button" track-type="feedback" track-name="sendFeedbackLink" track-metadata-position="footer" class="nocontent" project-icon="https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/images/favicons/onecloud/super_cloud.png" > <button> Send feedback </button> </devsite-feedback> <div class="devsite-floating-action-buttons"> </div> </article> <devsite-content-footer class="nocontent"> <p>Except as otherwise noted, the content of this page is licensed under the <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 License</a>, and code samples are licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 License</a>. For details, see the <a href="https://developers.google.com/site-policies">Google Developers Site Policies</a>. Java is a registered trademark of Oracle and/or its affiliates.</p> <p>Last updated 2025-02-14 UTC.</p> </devsite-content-footer> <devsite-notification > </devsite-notification> <div class="devsite-content-data"> <template class="devsite-thumb-rating-feedback"> <devsite-feedback position="thumb-rating" project-name="Recommender Documentation" product-id="5109002" bucket="Documentation" context="" version="t-devsite-webserver-20250218-r02-rc00.467092460105212566" data-label="Send Feedback Button" track-type="feedback" track-name="sendFeedbackLink" track-metadata-position="thumb-rating" class="nocontent" project-icon="https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/images/favicons/onecloud/super_cloud.png" > <button> Need to tell us more? </button> </devsite-feedback> </template> <template class="devsite-content-data-template"> [[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-02-14 UTC."],[],[]] </template> </div> </devsite-content> </main> <devsite-footer-promos class="devsite-footer"> </devsite-footer-promos> <devsite-footer-linkboxes class="devsite-footer"> <nav class="devsite-footer-linkboxes nocontent" aria-label="Footer links"> <ul class="devsite-footer-linkboxes-list"> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Why Google</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/why-google-cloud/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" track-metadata-module="footer"track-metadata-eventDetail="cloud.google.com/why-google-cloud/"track-metadata-position="footer"track-metadata-child_headline="why google"track-type="footer link"track-name="choosing google cloud"> Choosing Google Cloud </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/trust-center/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" track-metadata-eventDetail="cloud.google.com/security/"track-metadata-position="footer"track-name="trust and security"track-metadata-child_headline="why google"track-type="footer link"track-metadata-module="footer"> Trust and security </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/solutions/modern-infrastructure/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" track-metadata-position="footer"track-metadata-module="footer"track-metadata-child_headline="why google"track-type="footer link"track-metadata-eventDetail="cloud.google.com/solutions/modern-infrastructure/"track-name="modern infrastructure cloud"> Modern Infrastructure Cloud </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/multicloud/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" track-metadata-eventDetail="cloud.google.com/multicloud/"track-name="multicloud"track-metadata-position="footer"track-metadata-module="footer"track-metadata-child_headline="why google"track-type="footer link"> Multicloud </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/infrastructure/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" track-metadata-eventDetail="cloud.google.com/infrastructure/"track-metadata-child_headline="why google"track-name="global infrastructure"track-type="footer link"track-metadata-module="footer"track-metadata-position="footer"> Global infrastructure </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/customers/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" track-type="footer link"track-metadata-position="footer"track-metadata-eventDetail="cloud.google.com/customers/"track-metadata-child_headline="why google"track-name="customers and case studies"track-metadata-module="footer"> Customers and case studies </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/analyst-reports/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 7)" track-metadata-eventDetail="cloud.google.com/analyst-reports/"track-type="footer link"track-metadata-module="footer"track-metadata-child_headline="why google"track-name="analyst reports"track-metadata-position="footer"> Analyst reports </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/whitepapers/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 8)" track-metadata-eventDetail="cloud.google.com/whitepapers/"track-metadata-child_headline="why google"track-type="footer link"track-metadata-module="footer"track-name="whitepapers"track-metadata-position="footer"> Whitepapers </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//cloud.google.com/blog/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 9)" track-type="footer link"track-metadata-position="footer"track-metadata-module="footer"track-metadata-eventDetail="cloud.google.com/blog/"track-name="blog"track-metadata-child_headline="engage"> Blog </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Products and pricing</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/pricing/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" track-metadata-child_headline="products and pricing"track-metadata-position="footer"track-metadata-module="footer"track-metadata-eventDetail="cloud.google.com/pricing/"track-name="google cloud pricing"track-type="footer link"> Google Cloud pricing </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//workspace.google.com/pricing.html" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" track-type="footer link"track-name="google workspace pricing"track-metadata-child_headline="products and pricing"track-metadata-position="footer"track-metadata-eventDetail="workspace.google.com/pricing.html"target="_blank"track-metadata-module="footer"> Google Workspace pricing </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/products/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" track-type="footer link"track-metadata-eventDetail="cloud.google.com/products/"track-metadata-module="footer"track-name="see all products"track-metadata-position="footer"track-metadata-child_headline="products and pricing"> See all products </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Solutions</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/solutions/infrastructure-modernization/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" track-metadata-eventDetail="cloud.google.com/solutions/infrastructure-modernization/"track-type="footer link"track-name="infrastructure modernization"track-metadata-child_headline="solutions"track-metadata-position="footer"track-metadata-module="footer"> Infrastructure modernization </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/solutions/databases/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" track-type="footer link"track-metadata-position="footer"track-metadata-module="footer"track-metadata-eventDetail="cloud.google.com/solutions/databases"track-metadata-child_headline="solutions"track-name="databases"> Databases </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/solutions/application-modernization/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" track-metadata-module="footer"track-type="footer link"track-metadata-eventDetail="cloud.google.com/solutions/application-modernization/"track-metadata-child_headline="solutions"track-name="application development"track-metadata-position="footer"> Application modernization </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/solutions/smart-analytics/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" track-name="smart analytics"track-metadata-eventDetail="cloud.google.com/solutions/smart-analytics/"track-metadata-module="footer"track-metadata-child_headline="solutions"track-type="footer link"track-metadata-position="footer"> Smart analytics </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/solutions/ai/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" track-metadata-eventDetail="cloud.google.com/solutions/ai/"track-type="footer link"track-metadata-module="footer"track-name="artificial intelligence"track-metadata-child_headline="solutions"track-metadata-position="footer"> Artificial Intelligence </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/solutions/security/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" track-name="security"track-type="footer link"track-metadata-module="footer"track-metadata-position="footer"track-metadata-child_headline="solutions"track-metadata-eventDetail="cloud.google.com/solutions/security/"> Security </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://workspace.google.com/enterprise/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 7)" track-metadata-child_headline="solutions"track-type="footer link"track-metadata-module="footer"track-metadata-position="footer"target="_blank"track-metadata-eventDetail="workspace.google.com/enterprise/"track-name="productivity and work transformation"> Productivity & work transformation </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/solutions/#industry-solutions" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 8)" track-metadata-child_headline="solutions"track-metadata-position="footer"track-type="footer link"track-metadata-eventDetail="cloud.google.com/solutions/#industry-solutions"track-metadata-module="footer"track-name="industry solutions"> Industry solutions </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/solutions/devops/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 9)" track-type="footer link"track-metadata-module="footer"track-metadata-position="footer"track-name="devops solutions"track-metadata-eventDetail="cloud.google.com/solutions/devops/"track-metadata-child_headline="solutions"> DevOps solutions </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/solutions/#section-14" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 10)" track-name="small business solutions"track-metadata-child_headline="solutions"track-metadata-eventDetail="cloud.google.com/solutions/#section-14"track-metadata-position="footer"track-type="footer link"track-metadata-module="footer"> Small business solutions </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/solutions/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 11)" track-metadata-child_headline="solutions"track-type="footer link"track-metadata-position="footer"track-name="see all solutions"track-metadata-eventDetail="cloud.google.com/solutions/"track-metadata-module="footer"> See all solutions </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Resources</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/affiliate-program/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" track-metadata-child_headline="resources"track-metadata-position="footer"track-metadata-eventDetail="cloud.google.com/affiliate-program/"track-metadata-module="footer"track-name="google cloud affiliate program"track-type="footer link"> Google Cloud Affiliate Program </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/docs/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" track-metadata-position="footer"track-type="footer link"track-metadata-child_headline="resources"track-metadata-module="footer"track-metadata-eventDetail="cloud.google.com/docs/"track-name="google cloud documentation"> Google Cloud documentation </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/docs/get-started/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" track-metadata-module="footer"track-metadata-child_headline="resources"track-metadata-eventDetail="cloud.google.com/docs/get-started/"track-type="footer link"track-name="google cloud quickstarts"track-metadata-position="footer"> Google Cloud quickstarts </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/marketplace/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" track-metadata-eventDetail="cloud.google.com/marketplace/"track-metadata-child_headline="resources"track-name="google cloud marketplace"track-metadata-position="footer"track-metadata-module="footer"track-type="footer link"> Google Cloud Marketplace </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/discover/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" track-type="footer link"track-metadata-position="footer"track-metadata-module="footer"track-metadata-child_headline="resources"track-metadata-eventDetail="learn/"track-name="learn about cloud computing"> Learn about cloud computing </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/support-hub/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" track-metadata-position="footer"track-type="footer link"track-metadata-eventDetail="cloud.google.com/support-hub/"track-metadata-module="footer"track-name="support"track-metadata-child_headline="resources"> Support </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/docs/samples" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 7)" track-metadata-position="footer"track-metadata-module="footer"track-metadata-eventDetail="cloud.google.com/docs/samples"track-metadata-child_headline="resources"track-type="footer link"track-name="code samples"> Code samples </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/architecture/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 8)" track-metadata-module="footer"track-metadata-position="footer"track-metadata-child_headline="resources"track-metadata-eventDetail="cloud.google.com/architecture/"track-type="footer link"track-name="cloud architecture center"> Cloud Architecture Center </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/learn/training/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 9)" track-metadata-eventDetail="cloud.google.com/training/"track-metadata-module="footer"track-type="footer link"track-name="training"track-metadata-child_headline="resources"track-metadata-position="footer"> Training </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/learn/certification/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 10)" track-metadata-position="footer"track-type="footer link"track-metadata-child_headline="resources"track-metadata-eventDetail="cloud.google.com/certification"track-name="certifications"track-metadata-module="footer"> Certifications </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//developers.google.com" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 11)" target="_blank"track-metadata-eventDetail="developers.google.com"track-type="footer link"track-metadata-child_headline="resources"track-metadata-module="footer"track-metadata-position="footer"track-name="google developers"> Google for Developers </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/startup/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 12)" track-metadata-eventDetail="cloud.google.com/startup/"track-metadata-child_headline="resources"track-type="footer link"track-name="google cloud for startups"track-metadata-module="footer"track-metadata-position="footer"> Google Cloud for Startups </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//status.cloud.google.com" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 13)" track-name="system status"track-type="footer link"track-metadata-eventDetail="status.cloud.google.com"track-metadata-child_headline="resources"target="_blank"track-metadata-position="footer"track-metadata-module="footer"> System status </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/release-notes" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 14)" track-type="footer link"track-metadata-module="footer"track-metadata-eventDetail="cloud.google.com/release-notes/"track-metadata-child_headline="resources"track-name="release notes"track-metadata-position="footer"> Release Notes </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Engage</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/contact/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" track-name="contact sales"track-metadata-position="footer"track-metadata-child_headline="engage"track-metadata-module="footer"track-type="footer link"track-metadata-eventDetail="cloud.google.com/contact/"> Contact sales </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//cloud.google.com/find-a-partner" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" track-metadata-position="footer"track-metadata-child_headline="engage"target="_blank"track-type="footer link"track-metadata-eventDetail="cloud.google.com/find-a-partner"track-name="find a partner"track-metadata-module="footer"> Find a Partner </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/partners/become-a-partner/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" track-metadata-eventDetail="cloud.google.com/partners/become-a-partner/"track-name="become a partner"track-metadata-child_headline="engage"track-metadata-module="footer"track-type="footer link"track-metadata-position="footer"> Become a Partner </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/events/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" track-type="footer link"track-name="events"track-metadata-module="footer"track-metadata-child_headline="engage"track-metadata-position="footer"track-metadata-eventDetail="cloud.withgoogle.com/events"> Events </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/podcasts/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" track-metadata-module="footer"target="_blank"track-type="footer link"track-metadata-child_headline="engage"track-name="podcasts"rel="noopener"track-metadata-position="footer"track-metadata-eventDetail="cloud.google.com/podcasts/"> Podcasts </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/developers/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" track-name="developer center"track-metadata-module="footer"track-metadata-child_headline="engage"track-type="footer link"track-metadata-eventDetail="cloud.google.com/developers/"track-metadata-position="footer"> Developer Center </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://www.googlecloudpresscorner.com/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 7)" track-name="press corner"target="_blank"track-metadata-module="footer"rel="noopener"track-metadata-position="footer"track-metadata-eventDetail="www.googlecloudpresscorner.com"track-metadata-child_headline="engage"track-type="footer link"> Press Corner </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//www.youtube.com/googlecloud" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 8)" track-metadata-eventDetail="www.youtube.com/googlecloud"track-metadata-position="footer"target="_blank"track-type="footer link"track-metadata-module="footer"track-metadata-child_headline="engage"rel="noopener"track-name="google cloud on youtube"> Google Cloud on YouTube </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//www.youtube.com/googlecloudplatform" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 9)" track-name="google cloud tech on youtube"track-metadata-eventDetail="www.youtube.com/googlecloudplatform"target="_blank"track-metadata-position="footer"track-metadata-module="footer"rel="noopener"track-metadata-child_headline="engage"track-type="footer link"> Google Cloud Tech on YouTube </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//x.com/googlecloud" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 10)" target="_blank"track-type="footer link"track-metadata-module="footer"track-metadata-child_headline="engage"rel="noopener"track-metadata-position="footer"track-metadata-eventDetail="x.com/googlecloud"track-name="follow on x"> Follow on X </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//userresearch.google.com/?reserved=1&utm_source=website&Q_Language=en&utm_medium=own_srch&utm_campaign=CloudWebFooter&utm_term=0&utm_content=0&productTag=clou&campaignDate=jul19&pType=devel&referral_code=jk212693" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 11)" track-metadata-eventDetail="userresearch.google.com/?reserved=1&utm_source=website&Q_Language=en&utm_medium=own_srch&utm_campaign=CloudWebFooter&utm_term=0&utm_content=0&productTag=clou&campaignDate=jul19&pType=devel&referral_code=jk212693"track-type="footer link"track-name="join user research"track-metadata-module="footer"track-metadata-position="footer"target="_blank"track-metadata-child_headline="engage"> Join User Research </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//careers.google.com/cloud" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 12)" track-metadata-child_headline="engage"track-metadata-position="footer"target="_blank"track-metadata-eventDetail="careers.google.com/cloud"track-type="footer link"track-metadata-module="footer"track-name="we are hiring join google cloud"> We're hiring. Join Google Cloud! </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://www.googlecloudcommunity.com/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 13)" track-metadata-module="footer"track-metadata-eventDetail="www.googlecloudcommunity.com"track-name="google cloud community"target="_blank"track-metadata-child_headline="engage"track-type="footer link"rel="noopener"track-metadata-position="footer"> Google Cloud Community </a> </li> </ul> </li> </ul> </nav> </devsite-footer-linkboxes> <devsite-footer-utility class="devsite-footer"> <div class="devsite-footer-utility nocontent"> <nav class="devsite-footer-utility-links" aria-label="Utility links"> <ul class="devsite-footer-utility-list"> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//about.google/" data-category="Site-Wide Custom Events" data-label="Footer About Google link" track-metadata-position="footer" target="_blank" track-type="footer link" track-metadata-module="utility footer" track-metadata-eventDetail="//about.google/" track-name="about google" > About Google </a> </li> <li class="devsite-footer-utility-item devsite-footer-privacy-link"> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/privacy" data-category="Site-Wide Custom Events" data-label="Footer Privacy link" track-metadata-eventDetail="//policies.google.com/privacy" track-type="footer link" track-name="privacy" target="_blank" track-metadata-position="footer" track-metadata-module="utility footer" > Privacy </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//www.google.com/intl/en/policies/terms/regional.html" data-category="Site-Wide Custom Events" data-label="Footer Site terms link" target="_blank" track-type="footer link" track-metadata-module="utility footer" track-metadata-eventDetail="//www.google.com/intl/en/policies/terms/regional.html" track-name="site terms" track-metadata-position="footer" > Site terms </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="/product-terms/" data-category="Site-Wide Custom Events" data-label="Footer Google Cloud terms link" track-metadata-eventDetail="/product-terms/" track-name="google cloud terms" track-metadata-position="footer" track-type="footer link" track-metadata-module="utility footer" > Google Cloud terms </a> </li> <li class="devsite-footer-utility-item glue-cookie-notification-bar-control"> <a class="devsite-footer-utility-link gc-analytics-event" href="#" data-category="Site-Wide Custom Events" data-label="Footer Manage cookies link" track-name="Manage cookies" track-metadata-eventDetail="#" track-type="footer link" track-metadata-position="footer" track-metadata-module="utility footer" aria-hidden="true" > Manage cookies </a> </li> <li class="devsite-footer-utility-item devsite-footer-carbon-button"> <a class="devsite-footer-utility-link gc-analytics-event" href="/sustainability" data-category="Site-Wide Custom Events" data-label="Footer Our third decade of climate action: join us link" track-metadata-position="footer" track-type="footer link" track-metadata-module="utility footer" track-metadata-eventDetail="/sustainability/" track-name="Our third decade of climate action: join us" > Our third decade of climate action: join us </a> </li> <li class="devsite-footer-utility-item devsite-footer-utility-button"> <span class="devsite-footer-utility-description">Sign up for the Google Cloud newsletter</span> <a class="devsite-footer-utility-link gc-analytics-event" href="/newsletter/" data-category="Site-Wide Custom Events" data-label="Footer Subscribe link" track-type="footer link" track-name="subscribe" track-metadata-eventDetail="/newsletter/" track-metadata-position="footer" track-metadata-module="utility footer" > Subscribe </a> </li> </ul> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> </nav> </div> </devsite-footer-utility> <devsite-panel></devsite-panel> </section></section> <devsite-sitemask></devsite-sitemask> <devsite-snackbar></devsite-snackbar> <devsite-tooltip ></devsite-tooltip> <devsite-heading-link></devsite-heading-link> <devsite-analytics> <script type="application/json" analytics>[]</script> <script type="application/json" tag-management>{"at": "True", "ga4": [], "ga4p": [], "gtm": [{"id": "GTM-5CVQBG", "purpose": 1}], "parameters": {"internalUser": "False", "language": {"machineTranslated": "False", "requested": "en", "served": "en"}, "pageType": "article", "projectName": "Recommender Documentation", "signedIn": "False", "tenant": "cloud", "recommendations": {"sourcePage": "", "sourceType": 0, "sourceRank": 0, "sourceIdenticalDescriptions": 0, "sourceTitleWords": 0, "sourceDescriptionWords": 0, "experiment": ""}, "experiment": {"ids": ""}}}</script> </devsite-analytics> <devsite-badger></devsite-badger> <cloudx-user></cloudx-user> <cloudx-free-trial-eligible-store freeTrialEligible='true'></cloudx-free-trial-eligible-store> <cloudx-pricing-socket></cloudx-pricing-socket> <cloudx-experiments type="TestAACodivertedExperiment" path="/virtual/TestAACodivertedExperiment/configureExperiment" location="SG" variant="variant2" ></cloudx-experiments> <cloudx-experiment-ids userCountry="SG" devsiteExperimentIdList="[39300012, 39300020, 39300118, 39300192, 39300195, 39300241, 39300317, 39300320, 39300326, 39300346, 39300354, 39300363, 39300374, 39300412, 39300422, 39300436, 39300473, 39300488, 39300496, 39300498, 39300570]"> </cloudx-experiment-ids> <script nonce="eeY25lJAR1nCz99i898fVc+3UMVcln"> (function(d,e,v,s,i,t,E){d['GoogleDevelopersObject']=i; t=e.createElement(v);t.async=1;t.src=s;E=e.getElementsByTagName(v)[0]; E.parentNode.insertBefore(t,E);})(window, document, 'script', 'https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/js/app_loader.js', '[2,"en",null,"/js/devsite_app_module.js","https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018","https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud","https://cloud-dot-devsite-v2-prod.appspot.com",null,null,["/_pwa/cloud/manifest.json","https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/images/video-placeholder.svg","https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/images/favicons/onecloud/favicon.ico","https://www.gstatic.com/devrel-devsite/prod/vd2dddc2199cd18ccf014281c77515e1e906f6b98324fd2a8b5fa9e92b09e8018/cloud/images/cloud-logo.svg","https://fonts.googleapis.com/css?family=Google+Sans:400,500,700|Google+Sans+Text:400,400italic,500,500italic,700,700italic|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"],1,null,[1,6,8,12,14,17,21,25,50,52,63,70,75,76,80,87,91,92,93,97,98,100,101,102,103,104,105,107,108,109,110,112,113,117,118,120,122,124,125,126,127,129,130,131,132,133,134,135,136,138,140,141,147,148,149,151,152,156,157,158,159,161,163,164,168,169,170,179,180,182,183,186,191,193,196],"AIzaSyAP-jjEJBzmIyKR4F-3XITp8yM9T1gEEI8","AIzaSyB6xiKGDR5O3Ak2okS4rLkauxGUG7XP0hg","cloud.google.com","AIzaSyAQk0fBONSGUqCNznf6Krs82Ap1-NV6J4o","AIzaSyCCxcqdrZ_7QMeLCRY20bh_SXdAYqy70KY",null,null,null,["Cloud__enable_cloudx_ping","MiscFeatureFlags__enable_explain_this_code","Profiles__enable_release_notes_notifications","EngEduTelemetry__enable_engedu_telemetry","Analytics__enable_clearcut_logging","Profiles__enable_completecodelab_endpoint","Search__enable_ai_eligibility_checks","MiscFeatureFlags__enable_project_variables","DevPro__enable_cloud_innovators_plus","CloudShell__cloud_code_overflow_menu","Profiles__enable_completequiz_endpoint","Search__scope_to_project_tenant","Search__enable_ai_search_summaries_restricted","Profiles__enable_dashboard_curated_recommendations","CloudShell__cloud_shell_button","BookNav__enable_tenant_cache_key","TpcFeatures__enable_mirror_tenant_redirects","Profiles__require_profile_eligibility_for_signin","Profiles__enable_developer_profiles_callout","MiscFeatureFlags__enable_firebase_utm","Experiments__reqs_query_experiments","MiscFeatureFlags__emergency_css","Concierge__enable_concierge_restricted","Cloud__enable_cloud_shell","Cloud__enable_cloud_dlp_service","Search__enable_page_map","TpcFeatures__enable_unmirrored_page_left_nav","Cloud__enable_free_trial_server_call","Search__enable_ai_search_summaries","Cloud__enable_cloud_facet_chat","Cloud__enable_cloudx_experiment_ids","Search__enable_dynamic_content_confidential_banner","Profiles__enable_stripe_subscription_management","MiscFeatureFlags__developers_footer_image","Cloud__enable_legacy_calculator_redirect","Profiles__enable_recognition_badges","Cloud__enable_llm_concierge_chat","Profiles__enable_complete_playlist_endpoint","Profiles__enable_join_program_group_endpoint","MiscFeatureFlags__enable_variable_operator","Profiles__enable_public_developer_profiles","Cloud__enable_cloud_shell_fte_user_flow","Profiles__enable_page_saving","DevPro__enable_developer_subscriptions","MiscFeatureFlags__developers_footer_dark_image","Concierge__enable_pushui","Profiles__enable_profile_collections","Profiles__enable_awarding_url","MiscFeatureFlags__enable_view_transitions","Search__enable_suggestions_from_borg"],null,null,"AIzaSyBLEMok-5suZ67qRPzx0qUtbnLmyT_kCVE","https://developerscontentserving-pa.clients6.google.com","AIzaSyCM4QpTRSqP5qI4Dvjt4OAScIN8sOUlO-k","https://developerscontentsearch-pa.clients6.google.com",1,4,1,"https://developerprofiles-pa.clients6.google.com",[2,"cloud","Google Cloud","cloud.google.com",null,"cloud-dot-devsite-v2-prod.appspot.com",null,null,[1,1,null,null,null,null,null,null,null,null,null,[1],null,null,null,null,null,1,[1],[null,null,null,[1,20],"/terms/recommendations"],[1],null,[1],[1,null,1],[1,1,null,null,1,null,["/vertex-ai/"]]],null,[22,null,null,null,null,null,"/images/cloud-logo.svg","/images/favicons/onecloud/apple-icon.png",null,null,null,null,1,1,1,[6,5],[],null,null,[[],[],[],[],[],[],[],[]],null,1,null,null,null,null,[]],[],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[6,1,14,15,22,23,29,37],null,[[null,null,null,null,null,null,[1,[["docType","Choose a content type",[["ApiReference",null,null,null,null,null,null,null,null,"API reference"],["Sample",null,null,null,null,null,null,null,null,"Code sample"],["ReferenceArchitecture",null,null,null,null,null,null,null,null,"Reference architecture"],["Tutorial",null,null,null,null,null,null,null,null,"Tutorial"]]],["category","Choose a topic",[["AiAndMachineLearning",null,null,null,null,null,null,null,null,"Artificial intelligence and machine learning (AI/ML)"],["ApplicationDevelopment",null,null,null,null,null,null,null,null,"Application development"],["BigDataAndAnalytics",null,null,null,null,null,null,null,null,"Big data and analytics"],["Compute",null,null,null,null,null,null,null,null,"Compute"],["Containers",null,null,null,null,null,null,null,null,"Containers"],["Databases",null,null,null,null,null,null,null,null,"Databases"],["HybridCloud",null,null,null,null,null,null,null,null,"Hybrid and multicloud"],["LoggingAndMonitoring",null,null,null,null,null,null,null,null,"Logging and monitoring"],["Migrations",null,null,null,null,null,null,null,null,"Migrations"],["Networking",null,null,null,null,null,null,null,null,"Networking"],["SecurityAndCompliance",null,null,null,null,null,null,null,null,"Security and compliance"],["Serverless",null,null,null,null,null,null,null,null,"Serverless"],["Storage",null,null,null,null,null,null,null,null,"Storage"]]]]]],[1],null,1],[[null,null,null,null,null,["GTM-5CVQBG"],null,null,null,null,null,[["GTM-5CVQBG",2]],1],null,null,null,null,null,1],"mwETRvWii0eU5NUYprb0Y9z5GVbc",4,null,null,null,null,null,null,null,null,null,null,null,null,null,"cloud.devsite.google"],null,"pk_live_5170syrHvgGVmSx9sBrnWtA5luvk9BwnVcvIi7HizpwauFG96WedXsuXh790rtij9AmGllqPtMLfhe2RSwD6Pn38V00uBCydV4m",1]') </script> <devsite-a11y-announce></devsite-a11y-announce> </body> </html>