Initial commit
Some checks failed
Continuous Integration - Pull Request / code-tests (pull_request) Has been cancelled
Continuous Integration - Pull Request / deployment-tests (local-code) (pull_request) Has been cancelled
helm-chart-ci / helm-chart-ci (pull_request) Has been cancelled
kubevious-manifests-ci / kubevious-manifests-ci (pull_request) Has been cancelled
kustomize-build-ci / kustomize-build-ci (pull_request) Has been cancelled
terraform-validate-ci / terraform-validate-ci (pull_request) Has been cancelled
Clean up deployment / cleanup-namespace (pull_request) Has been cancelled
Continuous Integration - Main/Release / code-tests (push) Has been cancelled
Continuous Integration - Main/Release / deployment-tests (local-code) (push) Has been cancelled
helm-chart-ci / helm-chart-ci (push) Has been cancelled
kubevious-manifests-ci / kubevious-manifests-ci (push) Has been cancelled
kustomize-build-ci / kustomize-build-ci (push) Has been cancelled
terraform-validate-ci / terraform-validate-ci (push) Has been cancelled

This commit is contained in:
2026-02-04 20:47:56 +05:30
commit dafcd9777f
363 changed files with 52703 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
# The fields inside this deploystack.yaml file are documented in https://github.com/GoogleCloudPlatform/deploystack.
title: Microservices Demo (Online Boutique)
name: microservices-demo
duration: 5
collect_project: true
collect_region: true
region_type: compute
region_default: us-central1
hard_settings:
filepath_manifest: ../kustomize/
memorystore: "false"
name: online-boutique
namespace: default
documentation_link: https://cloud.google.com/shell/docs/cloud-shell-tutorials/deploystack/microservices-demo

View File

@@ -0,0 +1,4 @@
Online Boutique is a cloud-first microservices demo application. Online Boutique
consists of an 11-tier microservices application. The application is a web-based
e-commerce app where users can browse items, add them to the cart, and purchase
them.

View File

@@ -0,0 +1,4 @@
Congrats!
You have successfully provisioned a GKE (Google Kubernetes Engine) cluster and
deployed Online Boutique's 11 microservices, which includes a load generator.

16
.deploystack/scripts/preinit.sh Executable file
View File

@@ -0,0 +1,16 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ROOT=$(pwd)
sed -i.tmp "s/project_id/gcp_project_id/" $ROOT/terraform/terraform.tfvars

207
.deploystack/test Executable file
View File

@@ -0,0 +1,207 @@
#! /bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# DEPLOYSTACK - this file is a test script that is used by DeployStack's
# testing rig to make sure that the Terraform script installs and uninstalls
# cleanly
# DON'T REMOVE FROM test script.
CYAN='\033[0;36m'
BCYAN='\033[1;36m'
NC='\033[0m' # No Color
DIVIDER=$(printf %"$(tput cols)"s | tr " " "*")
DIVIDER+="\n"
function get_project_id() {
local __resultvar=$1
VALUE=$(gcloud config get-value project | xargs)
eval $__resultvar="'$VALUE'"
}
function get_project_number() {
local __resultvar=$1
local PRO=$2
VALUE=$(gcloud projects list --filter="project_id=$PRO" --format="value(PROJECT_NUMBER)" | xargs)
eval $__resultvar="'$VALUE'"
}
# DISPLAY HELPERS
function section_open() {
section_description=$1
printf "$DIVIDER"
printf "${CYAN}$section_description${NC} \n"
printf "$DIVIDER"
}
function section_close() {
printf "$DIVIDER"
printf "${CYAN}$section_description ${BCYAN}- done${NC}\n"
printf "\n\n"
}
function evalTest() {
local command=$1
local expected=$2
local ERR=""
got=$(eval $command 2>errFile)
ERR=$(<errFile)
if [ ${#ERR} -gt 0 ]; then
if [ "$expected" = "EXPECTERROR" ]; then
printf "ok \n"
return
fi
printf "expecting no error, got error='$ERR' \n"
exit 1
fi
if [ "$got" != "$expected" ]; then
printf "expecting: '$expected' got: '$got' \n"
exit 1
fi
printf "$expected is ok\n"
}
function generateProject(){
local __resultvar
local __STACKSUFFIX
local __BA
local __RANDOMSUFFIX
local __DATELABEL
local PROJECTID
local current
__resultvar=$1
__STACKSUFFIX=$2
__BA=$3
__RANDOMSUFFIX=$(
LC_ALL=C tr -dc 'a-z0-9' </dev/urandom | head -c 8
echo
)
__DATELABEL=$(date +%F)
PROJECTID=ds-test-$__STACKSUFFIX-$__RANDOMSUFFIX
current=$(gcloud config list account --format "value(core.account)")
# shellcheck disable=SC2034
GOOGLE_APPLICATION_CREDENTIALS=.deploystack/creds.json
gcloud projects create "$PROJECTID" --labels="deploystack-disposable-test-project=$__DATELABEL" --folder="155265971980"
gcloud auth activate-service-account --project="$PROJECTID" --key-file=.deploystack/creds.json -q
gcloud config set account test-runner@ds-tester-helper.iam.gserviceaccount.com -q
gcloud beta billing projects link "$PROJECTID" --billing-account="$__BA" -q
gcloud config set account "$current" -q
eval "$__resultvar"="'$PROJECTID'"
}
# END DON'T REMOVE FROM test script.
suffix=ms
# This is only needed if you tests fail alot because of overlapping runs of the
# same set of tests.
section_open "Generate random test project"
generateProject PROJECT "$suffix" "$BA"
section_close
# We need to force the use of gke-gcloud-auth-plugin (for GKE authentication)
# if we're using kubectl 1.25 or lower.
export USE_GKE_GCLOUD_AUTH_PLUGIN=True
DIR="terraform"
gcloud services enable cloudresourcemanager.googleapis.com --project=$PROJECT
REGION="us-central1"
NAME="online-boutique"
NAMESPACE="default"
FILEPATH_MANIFEST="../kustomize/"
MEMORYSTORE="false"
gcloud config set project ${PROJECT}
terraform -chdir="$DIR" init
terraform -chdir="$DIR" apply -auto-approve \
-var gcp_project_id="${PROJECT}" \
-var name="${NAME}" \
-var region="${REGION}" \
-var namespace="${NAMESPACE}" \
-var filepath_manifest="${FILEPATH_MANIFEST}" \
-var memorystore="${MEMORYSTORE}"
section_open "Testing Google Kubernetes Engine cluster exists"
evalTest 'gcloud container clusters describe online-boutique --format="value(name)" --region $REGION' "online-boutique"
section_close
section_open "Testing Online Boutique's services are running"
evalTest "kubectl get deployment adservice --no-headers -o=name 2> /dev/null" "deployment.apps/adservice"
evalTest "kubectl get deployment cartservice --no-headers -o=name 2> /dev/null" "deployment.apps/cartservice"
evalTest "kubectl get deployment checkoutservice --no-headers -o=name 2> /dev/null" "deployment.apps/checkoutservice"
evalTest "kubectl get deployment currencyservice --no-headers -o=name 2> /dev/null" "deployment.apps/currencyservice"
evalTest "kubectl get deployment emailservice --no-headers -o=name 2> /dev/null" "deployment.apps/emailservice"
evalTest "kubectl get deployment loadgenerator --no-headers -o=name 2> /dev/null" "deployment.apps/loadgenerator"
evalTest "kubectl get deployment paymentservice --no-headers -o=name 2> /dev/null" "deployment.apps/paymentservice"
evalTest "kubectl get deployment productcatalogservice --no-headers -o=name 2> /dev/null" "deployment.apps/productcatalogservice"
evalTest "kubectl get deployment recommendationservice --no-headers -o=name 2> /dev/null" "deployment.apps/recommendationservice"
evalTest "kubectl get deployment redis-cart --no-headers -o=name 2> /dev/null" "deployment.apps/redis-cart"
evalTest "kubectl get deployment shippingservice --no-headers -o=name 2> /dev/null" "deployment.apps/shippingservice"
section_close
sleep 120
ENDPOINT=$( kubectl get service frontend-external --no-headers 2> /dev/null | awk '{print $4}')
section_open "Testing Online Boutique's front-end is working"
evalTest 'curl -s -o /dev/null -w "%{http_code}" $ENDPOINT' "200"
section_close
# Uncomment the line: "deletion_protection = false"
sed -i "s/# deletion_protection/deletion_protection/g" ${DIR}/main.tf
terraform -chdir="$DIR" apply -auto-approve \
-var gcp_project_id="${PROJECT}" \
-var name="${NAME}" \
-var region="${REGION}" \
-var namespace="${NAMESPACE}" \
-var filepath_manifest="${FILEPATH_MANIFEST}" \
-var memorystore="${MEMORYSTORE}"
terraform -chdir="$DIR" destroy -auto-approve \
-var gcp_project_id="${PROJECT}" \
-var name="${NAME}" \
-var region="${REGION}" \
-var namespace="${NAMESPACE}" \
-var filepath_manifest="${FILEPATH_MANIFEST}" \
-var memorystore="${MEMORYSTORE}"
section_open "Testing Google Kubernetes Engine cluster does NOT exist"
evalTest 'gcloud container clusters describe online-boutique --format="value(name)" --region $REGION' "EXPECTERROR"
section_close
# This is only needed if you tests fail alot because of overlapping runs of the
# same set of tests. Really don't do this if you don't want to severely irritate
# @tpryan
section_open "Delete Test Project"
gcloud projects delete $PROJECT -q
section_close
printf "$DIVIDER"
printf "CONGRATS!!!!!!! \n"
printf "You got the end the of your test with everything working. \n"
printf "$DIVIDER"

35
.deploystack/test.yaml Normal file
View File

@@ -0,0 +1,35 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# DEPLOYSTACK - this file is the cloudbuild for running testing automatically
# in the testing rig
steps:
- name: 'bash'
id: "creds"
args: ['-c','echo $$CREDS > .deploystack/creds.json']
secretEnv: ['CREDS']
- name: 'gcr.io/cloudshell-images/cloudshell:latest'
entrypoint: bash
args: [ '.deploystack/test' ]
secretEnv: ['BA']
timeout: 4200s
options:
machineType: 'E2_HIGHCPU_8'
availableSecrets:
secretManager:
- versionName: projects/$PROJECT_ID/secrets/creds/versions/latest
env: 'CREDS'
- versionName: projects/$PROJECT_ID/secrets/billing_account/versions/latest
env: 'BA'

26
.editorconfig Normal file
View File

@@ -0,0 +1,26 @@
# The .editorconfig is used to maintain consistent code style.
# The .editorconfig file is supported by most text editors.
# See https://editorconfig.org
root = true
[*]
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.cs]
indent_size = 4
[Dockerfile*]
indent_size = 4
[*.go]
indent_style = tab
[*.java]
indent_size = 4
[*.py]
indent_size = 4

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
# This file configures the git settings for this repository.
# Converts "CR + LF" to "LF", for all "text" files — for local files on all OSes and files pushed to the remote repo.
* text=auto eol=lf

6
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,6 @@
# See https://help.github.com/en/articles/about-code-owners
# for more info about CODEOWNERS file.
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence.
* @GoogleCloudPlatform/devrel-flagship-app-maintainers @yoshi-approver

43
.github/CODE_OF_CONDUCT.md vendored Normal file
View File

@@ -0,0 +1,43 @@
# Contributor Code of Conduct
As contributors and maintainers of this project,
and in the interest of fostering an open and welcoming community,
we pledge to respect all people who contribute through reporting issues,
posting feature requests, updating documentation,
submitting pull requests or patches, and other activities.
We are committed to making participation in this project
a harassment-free experience for everyone,
regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information,
such as physical or electronic
addresses, without explicit permission
* Other unethical or unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct.
By adopting this Code of Conduct,
project maintainers commit themselves to fairly and consistently
applying these principles to every aspect of managing this project.
Project maintainers who do not follow or enforce the Code of Conduct
may be permanently removed from the project team.
This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior
may be reported by opening an issue
or contacting one or more of the project maintainers.
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0,
available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)

34
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,34 @@
# How to Contribute
Thank you so much for your interest in contributing to Online Boutique.
Before contributing, you must:
* Sign the [Contributor License Agreement (CLA)](#contributor-license-agreement).
* Follow the [Google Open Source Community Guidelines](https://opensource.google.com/conduct/).
* Follow the [Contribution Process](#contribution-process).
## Contributor License Agreement
Contributions to Online Boutique must be accompanied by a Contributor License
Agreement (CLA). You (or your employer) retain the copyright to your contribution.
The CLA gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Contribution Process
Here's the process for making a change to this repository:
1. Review Online Boutique's [purpose](/docs/purpose.md) and [product requirements](/docs/product-requirements.md).
1. If your proposed changes **do not align** with the purpose and product requirements of Online Boutique, you may be asked to instead maintain your own fork of this repository.
1. For **small changes** (such as a bug fixes or spelling corrections):
1. Fork this repository and submit a [pull request](https://help.github.com/articles/about-pull-requests/).
1. Wait for a maintainer of this repository to review your change.
1. For **bigger changes**:
1. Create a [GitHub issue](https://github.com/GoogleCloudPlatform/microservices-demo/issues/new/choose) describing the change **before** working on the implementation. This is important to avoid potentially having to discard your development efforts.
1. Wait for a maintainer of this repository to review your GitHub issue. For significantly complex proposals, you may be asked to start a Google Doc to discuss design decisions.
If you have any questions, please [create a GitHub issue](https://github.com/GoogleCloudPlatform/microservices-demo/issues/new/choose).

34
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@@ -0,0 +1,34 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
### Describe the bug
<!-- A clear and concise description of what the bug is. -->
### To Reproduce
<!-- Steps to reproduce the behavior: -->
<!-- 1. Built image '...' -->
<!-- 2. Ran command '....' -->
<!-- 3. See error -->
### Logs
<!-- Add logs to help explain your problem -->
### Screenshots
<!-- If applicable, add screenshots to help explain your problem -->
### Environment
<!-- - OS: [e.g. MacOS Big Sur v11.6] -->
<!-- - Kubernetes distribution, version: [e.g. minikube, GKE (Standard or Autopilot), EKS, AWS ... ] -->
<!-- - Any relevant tool version: [e.g. Docker v20.10.8] -->
### Additional context
<!-- Add any other context about the problem here -->
### Exposure
<!-- Is the bug intermittent, persistent? Is it widespread, local? -->

View File

@@ -0,0 +1,14 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
### Describe request or inquiry
<!-- Add any other context about the problem or helpful links here! -->
### What purpose/environment will this feature serve?
<!-- Add reasoning -->

10
.github/ISSUE_TEMPLATE/other.md vendored Normal file
View File

@@ -0,0 +1,10 @@
---
name: Other
about: Have a question or need clarification?
title: ''
labels: ''
assignees: ''
---
### Write down your inquiry
<!-- Write your question/inquiry here and any addition context -->

7
.github/SECURITY.md vendored Normal file
View File

@@ -0,0 +1,7 @@
# Security Policy
To report a security issue, please use [g.co/vulnz](https://g.co/vulnz).
The Google Security Team will respond within 5 working days of your report on g.co/vulnz.
We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue.

23
.github/auto-approve.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# https://github.com/googleapis/repo-automation-bots/tree/main/packages/auto-approve
processes:
- "PythonDependency"
- "PythonSampleAppDependency"
- "JavaDependency"
- "JavaSampleAppDependency"
- "GoDependency"
- "NodeDependency"
- "DockerDependency"

47
.github/header-checker-lint.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This file configures a GitHub Bot called "License Header Lint GCF": https://github.com/apps/license-header-lint-gcf
# The bot runs a GitHub check called "header-check" (inside pull-requests) that warns us about invalid/missing license headers.
# The schema for this configutation file is documented at https://github.com/googleapis/repo-automation-bots/tree/main/packages/header-checker-lint#header-checker-lint.
allowedCopyrightHolders:
- 'Google LLC'
allowedLicenses:
- 'Apache-2.0'
# If you want to ignore certain files/folders, use ignoreFiles.
# ignoreFiles:
# - '**/requirements.txt'
# If you want to ignore checking the license year, use ignoreLicenseYear.
# ignoreLicenseYear: true # Useful when migrating in code licensed at previous years.
sourceFileExtensions:
- 'cs'
- 'css'
- 'Dockerfile'
- 'dockerignore'
- 'gitignore'
- 'go'
- 'html'
- 'java'
- 'js'
- 'proto'
- 'py'
- 'sh'
- 'tf'
- 'yaml'
- 'yml'

16
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,16 @@
### Background
<!-- What was happening before this PR, and the problem(s) it solves -->
### Fixes
<!-- Link the issue(s) this PR fixes-->
### Change Summary
<!-- Short summary of the changes submitted -->
### Additional Notes
<!-- Any remaining concerns -->
### Testing Procedure
<!-- If applicable, write how to test for reviewers-->
### Related PRs or Issues
<!-- Dependent PRs, or any relevant linked issues -->

75
.github/release-cluster/README.md vendored Normal file
View File

@@ -0,0 +1,75 @@
# cymbal-shops.retail.cymbal.dev manifests
This directory contains extra deploy manifests for configuring Online Boutique solution on GKE for cymbal-shops.retail.cymbal.dev.
_Note: before moving forward, the Online Boutique apps should already be deployed [on the online-boutique-release GKE cluster](/docs/releasing#10-deploy-releasekubernetes-manifestsyaml-to-our-online-boutique-release-gke-cluster)._
## Public static IP address
Create the static public IP address:
```
STATIC_IP_NAME=online-boutique-ip # name hard-coded in: frontend-ingress.yaml
gcloud compute addresses create $STATIC_IP_NAME --global
```
When ready to do so, you could grab this public IP address and update your DNS:
```
gcloud compute addresses describe $STATIC_IP_NAME \
--global \
--format "value(address)"
```
## Cloud Armor
Set up Cloud Armor:
```
SECURITY_POLICY_NAME=online-boutique-security-policy # Name hard-coded in: backendconfig.yaml
gcloud compute security-policies create $SECURITY_POLICY_NAME \
--description "Block various attacks"
gcloud compute security-policies rules create 1000 \
--security-policy $SECURITY_POLICY_NAME \
--expression "evaluatePreconfiguredExpr('xss-stable')" \
--action "deny-403" \
--description "XSS attack filtering"
gcloud compute security-policies rules create 12345 \
--security-policy $SECURITY_POLICY_NAME \
--expression "evaluatePreconfiguredExpr('cve-canary')" \
--action "deny-403" \
--description "CVE-2021-44228 and CVE-2021-45046"
gcloud compute security-policies update $SECURITY_POLICY_NAME \
--enable-layer7-ddos-defense
gcloud compute security-policies update $SECURITY_POLICY_NAME \
--log-level=VERBOSE
```
## SSL Policy
Set up an SSL policy in order to later set up a redirect from HTTP to HTTPs:
```
SSL_POLICY_NAME=online-boutique-ssl-policy # Name hard-coded in: frontendconfig.yaml
gcloud compute ssl-policies create $SSL_POLICY_NAME \
--profile COMPATIBLE \
--min-tls-version 1.0
```
## Deploy Kubernetes manifests
Deploy the Kubernetes manifests in this current folder:
```
kubectl apply -f .
```
Wait for the `ManagedCertificate` to be provisioned. This usually takes about 30 minutes.
```
kubectl get managedcertificates
```
Remove the default `LoadBalancer` `Service` not used at this point:
```
kubectl delete service frontend-external
```
Remove the `loadgenerator` `Deployment` not used at this point:
```
kubectl delete deployment loadgenerator
```

View File

@@ -0,0 +1,21 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: frontend-backend-config
spec:
securityPolicy:
name: online-boutique-security-policy

View File

@@ -0,0 +1,23 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
name: frontend-frontend-config
spec:
sslPolicy: online-boutique-ssl-policy
redirectToHttps:
enabled: true
responseCodeName: MOVED_PERMANENTLY_DEFAULT

View File

@@ -0,0 +1,38 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: frontend-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: online-boutique-ip
networking.gke.io/managed-certificates: online-boutique-certificate
networking.gke.io/v1beta1.FrontendConfig: frontend-frontend-config
spec:
defaultBackend:
service:
name: frontend
port:
number: 80
rules:
- http:
paths:
- path: /*
pathType: ImplementationSpecific
backend:
service:
name: frontend
port:
number: 80

View File

@@ -0,0 +1,29 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: v1
kind: Service
metadata:
name: frontend
annotations:
cloud.google.com/neg: '{"ingress": true}'
cloud.google.com/backend-config: '{"default": "frontend-backend-config"}'
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
port: 80
targetPort: 8080

View File

@@ -0,0 +1,21 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: online-boutique-certificate
spec:
domains:
- cymbal-shops.retail.cymbal.dev

27
.github/renovate.json5 vendored Normal file
View File

@@ -0,0 +1,27 @@
{
extends: [
'github>GoogleCloudPlatform/kubernetes-engine-samples//.github/renovate-configs/dee-platform-ops.json5',
'schedule:earlyMondays',
],
'pip-compile': {
enabled: true,
managerFilePatterns: [
'/(^|/)requirements\\.txt$/',
],
},
pip_requirements: {
enabled: false,
},
constraints: {
python: '~=3.11.0',
},
kubernetes: {
managerFilePatterns: [
'/\\.yaml$/',
],
ignorePaths: [
'release/**',
'kustomize/base/**',
],
},
}

14
.github/snippet-bot.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

15
.github/terraform/README.md vendored Normal file
View File

@@ -0,0 +1,15 @@
This folder contains the Terraform for some of the infrastructure used by the CICD (continuous integration and continuous delivery/continuous deployment) of this repository.
## Update this Terraform
To make changes to this Terraform, follow these steps:
1. Make sure you have access to the `online-boutique-ci` Google Cloud project.
1. Move into this folder: `cd .github/terraform`
1. Set the PROJECT_ID environment variable: `export PROJECT_ID=online-boutique-ci`
1. Prepare Terraform and download the necessary Terraform dependencies (such as the "hashicorp/google" Terraform provider): `terraform init`
1. Apply the Terraform: `terraform apply -var project_id=${PROJECT_ID}`
* Ideally, you would see `Apply complete! Resources: 0 added, 0 changed, 0 destroyed.` in the output.
1. Make your desired changes to the Terraform code.
1. Apply the Terraform: `terraform apply -var project_id=${PROJECT_ID}`
* This time, Terraform will prompt you confirm your changes before applying them.

116
.github/terraform/main.tf vendored Normal file
View File

@@ -0,0 +1,116 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
# Set defaults for the google Terraform provider.
provider "google" {
project = var.project_id
region = "us-central1"
zone = "us-central1-a"
}
terraform {
# Store the state inside a Google Cloud Storage bucket.
backend "gcs" {
bucket = "cicd-terraform-state"
prefix = "terraform-state"
}
}
# Enable Google Cloud APIs.
module "enable_google_apis" {
source = "terraform-google-modules/project-factory/google//modules/project_services"
version = "~> 18.0"
disable_services_on_destroy = false
activate_apis = [
"cloudresourcemanager.googleapis.com",
"container.googleapis.com",
"iam.googleapis.com",
"storage.googleapis.com",
]
project_id = var.project_id
}
# Google Cloud Storage for storing Terraform state (.tfstate).
resource "google_storage_bucket" "terraform_state_storage_bucket" {
name = "cicd-terraform-state"
location = "us"
storage_class = "STANDARD"
force_destroy = false
public_access_prevention = "enforced"
uniform_bucket_level_access = true
versioning {
enabled = true
}
}
# Google Cloud IAM service account for GKE clusters.
# We avoid using the Compute Engine default service account because it's too permissive.
resource "google_service_account" "gke_clusters_service_account" {
account_id = "gke-clusters-service-account"
display_name = "My Service Account"
depends_on = [
module.enable_google_apis
]
}
# See https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa
resource "google_project_iam_member" "gke_clusters_service_account_role_metric_writer" {
project = var.project_id
role = "roles/monitoring.metricWriter"
member = "serviceAccount:${google_service_account.gke_clusters_service_account.email}"
}
# See https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa
resource "google_project_iam_member" "gke_clusters_service_account_role_logging_writer" {
project = var.project_id
role = "roles/logging.logWriter"
member = "serviceAccount:${google_service_account.gke_clusters_service_account.email}"
}
# See https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa
resource "google_project_iam_member" "gke_clusters_service_account_role_monitoring_viewer" {
project = var.project_id
role = "roles/monitoring.viewer"
member = "serviceAccount:${google_service_account.gke_clusters_service_account.email}"
}
# See https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa
resource "google_project_iam_member" "gke_clusters_service_account_role_stackdriver_writer" {
project = var.project_id
role = "roles/stackdriver.resourceMetadata.writer"
member = "serviceAccount:${google_service_account.gke_clusters_service_account.email}"
}
# The GKE cluster used for pull-request (PR) staging deployments.
resource "google_container_cluster" "prs_gke_cluster" {
name = "prs-gke-cluster"
location = "us-central1"
enable_autopilot = true
project = var.project_id
deletion_protection = true
depends_on = [
module.enable_google_apis
]
cluster_autoscaling {
auto_provisioning_defaults {
service_account = google_service_account.gke_clusters_service_account.email
}
}
# Need an empty ip_allocation_policy to overcome an error related to autopilot node pool constraints.
# Workaround from https://github.com/hashicorp/terraform-provider-google/issues/10782#issuecomment-1024488630
ip_allocation_policy {
}
}

23
.github/terraform/variables.tf vendored Normal file
View File

@@ -0,0 +1,23 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
# This file lists variables that you can set using the -var flag during "terraform apply".
# Example: terraform apply -var project_id="${PROJECT_ID}"
variable "project_id" {
type = string
description = "The Google Cloud project ID."
}

25
.github/terraform/versions.tf vendored Normal file
View File

@@ -0,0 +1,25 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
terraform {
required_version = ">= 0.13"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 7.0"
}
}
}

65
.github/workflows/README.md vendored Normal file
View File

@@ -0,0 +1,65 @@
# GitHub Actions Workflows
This page describes the CI/CD workflows for the Online Boutique app, which run in [Github Actions](https://github.com/GoogleCloudPlatform/microservices-demo/actions).
## Infrastructure
The CI/CD pipelines for Online Boutique run in Github Actions, using a pool of two [self-hosted runners]((https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-self-hosted-runners)). These runners are GCE instances (virtual machines) that, for every open Pull Request in the repo, run the code test pipeline, deploy test pipeline, and (on main) deploy the latest version of the app to [cymbal-shops.retail.cymbal.dev](https://cymbal-shops.retail.cymbal.dev)
We also host a test GKE cluster, which is where the deploy tests run. Every PR has its own namespace in the cluster.
## Workflows
**Note**: In order for the current CI/CD setup to work on your pull request, you must branch directly off the repo (no forks). This is because the Github secrets necessary for these tests aren't copied over when you fork.
### Code Tests - [ci-pr.yaml](ci-pr.yaml)
These tests run on every commit for every open PR, as well as any commit to main / any release branch. Currently, this workflow runs only Go unit tests.
### Deploy Tests- [ci-pr.yaml](ci-pr.yaml)
These tests run on every commit for every open PR, as well as any commit to main / any release branch. This workflow:
1. Creates a dedicated GKE namespace for that PR, if it doesn't already exist, in the PR GKE cluster.
2. Uses `skaffold run` to build and push the images specific to that PR commit. Then skaffold deploys those images, via `kubernetes-manifests`, to the PR namespace in the test cluster.
3. Tests to make sure all the pods start up and become ready.
4. Gets the LoadBalancer IP for the frontend service.
5. Comments that IP in the pull request, for staging.
### Push and Deploy Latest - [push-deploy](push-deploy.yml)
This is the Continuous Deployment workflow, and it runs on every commit to the main branch. This workflow:
1. Builds the container images for every service, tagging as `latest`.
2. Pushes those images to Google Container Registry.
Note that this workflow does not update the image tags used in `release/kubernetes-manifests.yaml` - these release manifests are tied to a stable `v0.x.x` release.
### Cleanup - [cleanup.yaml](cleanup.yaml)
This workflow runs when a PR closes, regardless of whether it was merged into main. This workflow deletes the PR-specific GKE namespace in the test cluster.
## Appendix - Creating a new Actions runner
Should one of the two self-hosted Github Actions runners (GCE instances) fail, or you want to add more runner capacity, this is how to provision a new runner. Note that you need IAM access to the admin Online Boutique GCP project in order to do this.
1. Create a GCE instance.
- VM should be at least n1-standard-4 with 50GB persistent disk
- VM should use custom service account with permissions to: access a GKE cluster, create GCS storage buckets, and push to GCR.
2. SSH into new VM through the Google Cloud Console.
3. Install project-specific dependencies, including go, docker, skaffold, and kubectl:
```
wget -O - https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/.github/workflows/install-dependencies.sh | bash
```
The instance will restart when the script completes in order to finish the Docker install.
4. SSH back into the VM.
5. Follow the instructions to add a new runner on the [Actions Settings page](https://github.com/GoogleCloudPlatform/microservices-demo/settings/actions) to authenticate the new runner
6. Start GitHub Actions as a background service:
```
sudo ~/actions-runner/svc.sh install ; sudo ~/actions-runner/svc.sh start
```

122
.github/workflows/ci-main.yaml vendored Normal file
View File

@@ -0,0 +1,122 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: "Continuous Integration - Main/Release"
on:
push:
# run on pushes to main or release/*
branches:
- main
- release/*
paths-ignore:
- '**/README.md'
- 'kustomize/**'
- '.github/workflows/kustomize-build-ci.yaml'
- 'terraform/**'
- '.github/workflows/terraform-validate-ci.yaml'
- 'helm-chart/**'
- '.github/workflows/helm-chart-ci.yaml'
jobs:
code-tests:
runs-on: [self-hosted, is-enabled]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
env:
DOTNET_INSTALL_DIR: "./.dotnet"
with:
dotnet-version: '10.0'
- uses: actions/setup-go@v6
with:
go-version: '1.25'
- name: Go Unit Tests
timeout-minutes: 10
run: |
for SERVICE in "shippingservice" "productcatalogservice"; do
echo "testing $SERVICE..."
pushd src/$SERVICE
go test
popd
done
- name: C# Unit Tests
timeout-minutes: 10
run: |
dotnet test src/cartservice/
deployment-tests:
runs-on: [self-hosted, is-enabled]
needs: code-tests
strategy:
matrix:
profile: ["local-code"]
fail-fast: true
steps:
- uses: actions/checkout@v6
- name: Build + Deploy PR images to GKE
timeout-minutes: 20
run: |
PR_NUMBER=$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')
NAMESPACE="pr${PR_NUMBER}"
echo "::set-env name=NAMESPACE::$NAMESPACE"
echo "::set-env name=PR_NUMBER::$PR_NUMBER"
yes | gcloud auth configure-docker us-docker.pkg.dev
gcloud container clusters get-credentials $PR_CLUSTER --region $REGION --project $PROJECT_ID
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: $NAMESPACE
EOF
echo Deploying application
skaffold config set --global local-cluster false
skaffold run --default-repo=us-docker.pkg.dev/$PROJECT_ID/$GITHUB_REF --tag=$GITHUB_SHA --namespace=$NAMESPACE -p network-policies
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
PROJECT_ID: "online-boutique-ci"
PR_CLUSTER: "prs-gke-cluster"
REGION: "us-central1"
- name: Wait For Pods
timeout-minutes: 20
run: |
set -x
kubectl config set-context --current --namespace=$NAMESPACE
kubectl wait --for=condition=available --timeout=1000s deployment/redis-cart
kubectl wait --for=condition=available --timeout=1000s deployment/adservice
kubectl wait --for=condition=available --timeout=1000s deployment/cartservice
kubectl wait --for=condition=available --timeout=1000s deployment/checkoutservice
kubectl wait --for=condition=available --timeout=1000s deployment/currencyservice
kubectl wait --for=condition=available --timeout=1000s deployment/emailservice
kubectl wait --for=condition=available --timeout=1000s deployment/frontend
kubectl wait --for=condition=available --timeout=1000s deployment/loadgenerator
kubectl wait --for=condition=available --timeout=1000s deployment/paymentservice
kubectl wait --for=condition=available --timeout=1000s deployment/productcatalogservice
kubectl wait --for=condition=available --timeout=1000s deployment/recommendationservice
kubectl wait --for=condition=available --timeout=1000s deployment/shippingservice
- name: Smoke Test
timeout-minutes: 5
run: |
set -x
# start fresh loadgenerator pod
kubectl delete pod -l app=loadgenerator
# wait for requests to come in
REQUEST_COUNT="0"
while [[ "$REQUEST_COUNT" -lt "50" ]]; do
sleep 5
REQUEST_COUNT=$(kubectl logs -l app=loadgenerator | grep Aggregated | awk '{print $2}')
done
# ensure there are no errors hitting endpoints
ERROR_COUNT=$(kubectl logs -l app=loadgenerator | grep Aggregated | awk '{print $3}' | sed "s/[(][^)]*[)]//g")
if [[ "$ERROR_COUNT" -gt "0" ]]; then
exit 1
fi

158
.github/workflows/ci-pr.yaml vendored Normal file
View File

@@ -0,0 +1,158 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: "Continuous Integration - Pull Request"
on:
pull_request:
branches:
- main
paths-ignore:
- '**/README.md'
- 'kustomize/**'
- '.github/workflows/kustomize-build-ci.yaml'
- 'terraform/**'
- '.github/workflows/terraform-validate-ci.yaml'
- 'helm-chart/**'
- '.github/workflows/helm-chart-ci.yaml'
# Ensure this workflow only runs for the most recent commit of a pull-request
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
code-tests:
runs-on: [self-hosted, is-enabled]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
env:
DOTNET_INSTALL_DIR: "./.dotnet"
with:
dotnet-version: '10.0'
- uses: actions/setup-go@v6
with:
go-version: '1.25'
- name: Go Unit Tests
timeout-minutes: 10
run: |
for GO_PACKAGE in "shippingservice" "productcatalogservice" "frontend/validator"; do
echo "Testing $GO_PACKAGE..."
pushd src/$GO_PACKAGE
go test
popd
done
- name: C# Unit Tests
timeout-minutes: 10
run: |
dotnet test src/cartservice/
deployment-tests:
runs-on: [self-hosted, is-enabled]
needs: code-tests
strategy:
matrix:
profile: ["local-code"]
fail-fast: true
steps:
- uses: actions/checkout@v6
with:
ref: ${{github.event.pull_request.head.sha}}
- name: Build + Deploy PR images to GKE
timeout-minutes: 20
run: |
NAMESPACE="pr${PR_NUMBER}"
echo "::set-env name=NAMESPACE::$NAMESPACE"
yes | gcloud auth configure-docker us-docker.pkg.dev
gcloud container clusters get-credentials $PR_CLUSTER --region $REGION --project $PROJECT_ID
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: $NAMESPACE
EOF
echo Deploying application
skaffold config set --global local-cluster false
skaffold run --default-repo=us-docker.pkg.dev/$PROJECT_ID/refs/pull/$PR_NUMBER --tag=$PR_NUMBER --namespace=$NAMESPACE -p network-policies
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
PR_NUMBER: ${{ github.event.pull_request.number }}
PROJECT_ID: "online-boutique-ci"
PR_CLUSTER: "prs-gke-cluster"
REGION: "us-central1"
- name: Wait For Pods
timeout-minutes: 20
run: |
set -x
kubectl config set-context --current --namespace=$NAMESPACE
kubectl wait --for=condition=available --timeout=1000s deployment/redis-cart
kubectl wait --for=condition=available --timeout=1000s deployment/adservice
kubectl wait --for=condition=available --timeout=1000s deployment/cartservice
kubectl wait --for=condition=available --timeout=1000s deployment/checkoutservice
kubectl wait --for=condition=available --timeout=1000s deployment/currencyservice
kubectl wait --for=condition=available --timeout=1000s deployment/emailservice
kubectl wait --for=condition=available --timeout=1000s deployment/frontend
kubectl wait --for=condition=available --timeout=1000s deployment/loadgenerator
kubectl wait --for=condition=available --timeout=1000s deployment/paymentservice
kubectl wait --for=condition=available --timeout=1000s deployment/productcatalogservice
kubectl wait --for=condition=available --timeout=1000s deployment/recommendationservice
kubectl wait --for=condition=available --timeout=1000s deployment/shippingservice
- name: Query EXTERNAL_IP for staging
timeout-minutes: 5
run: |
set -x
NAMESPACE="pr${PR_NUMBER}"
get_externalIP() {
kubectl get service frontend-external --namespace $NAMESPACE -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
}
until [[ -n "$(get_externalIP)" ]]; do
echo "Querying for external IP for frontend-external on namespace: $NAMESPACE{}"
sleep 3
done
EXTERNAL_IP=$(get_externalIP)
echo "::set-env name=EXTERNAL_IP::$EXTERNAL_IP"
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
PR_NUMBER: ${{ github.event.pull_request.number }}
- name: Smoke Test
timeout-minutes: 5
run: |
set -x
# start fresh loadgenerator pod
kubectl delete pod -l app=loadgenerator
# wait for requests to come in
REQUEST_COUNT="0"
while [[ "$REQUEST_COUNT" -lt "50" ]]; do
sleep 5
REQUEST_COUNT=$(kubectl logs -l app=loadgenerator | grep Aggregated | awk '{print $2}')
done
# ensure there are no errors hitting endpoints
ERROR_COUNT=$(kubectl logs -l app=loadgenerator | grep Aggregated | awk '{print $3}' | sed "s/[(][^)]*[)]//g")
if [[ "$ERROR_COUNT" -gt "0" ]]; then
exit 1
fi
- name: Comment EXTERNAL_IP
timeout-minutes: 5
env:
COMMENTS_URL: ${{ github.event.pull_request.comments_url }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl \
-X POST \
$COMMENTS_URL \
-H "Content-Type: application/json" \
-H "Authorization: token $GITHUB_TOKEN" \
--data '{ "body": "🚲 PR staged at '"http://${EXTERNAL_IP}"'"}'
sleep 60

44
.github/workflows/cleanup.yaml vendored Normal file
View File

@@ -0,0 +1,44 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: "Clean up deployment"
on:
pull_request:
# run on pull requests targeting main
branches:
- main
types: closed
paths-ignore:
- '**/README.md'
- 'kustomize/**'
- '.github/workflows/kustomize-build-ci.yaml'
- 'terraform/**'
- '.github/workflows/terraform-validate-ci.yaml'
jobs:
cleanup-namespace:
runs-on: [self-hosted, is-enabled]
steps:
- name: Delete PR namespace in staging cluster
if: ${{ always() }}
timeout-minutes: 20
run: |
gcloud container clusters get-credentials $PR_CLUSTER \
--region $REGION --project $PROJECT_ID
NAMESPACE="pr${PR_NUMBER}"
kubectl delete namespace $NAMESPACE
env:
PROJECT_ID: "online-boutique-ci"
PR_CLUSTER: "prs-gke-cluster"
REGION: "us-central1"
PR_NUMBER: ${{ github.event.number }}

107
.github/workflows/helm-chart-ci.yaml vendored Normal file
View File

@@ -0,0 +1,107 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: helm-chart-ci
on:
push:
branches:
- main
paths:
- 'helm-chart/**'
- '.github/workflows/helm-chart-ci.yaml'
pull_request:
paths:
- 'helm-chart/**'
- '.github/workflows/helm-chart-ci.yaml'
jobs:
helm-chart-ci:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: helm lint
run: |
cd helm-chart/
helm lint --strict
- name: helm template default
run: |
cd helm-chart/
helm template . > helm-template.yaml
cat helm-template.yaml
kustomize create --resources helm-template.yaml
kustomize build .
- name: helm template grpc health probes
run: |
# Test related to https://medium.com/google-cloud/b5bd26253a4c
cd helm-chart/
SPANNER_CONNECTION_STRING=projects/PROJECT_ID/instances/SPANNER_INSTANCE_NAME/databases/SPANNER_DATABASE_NAME
helm template . \
--set nativeGrpcHealthCheck=true \
-n onlineboutique \
> helm-template.yaml
cat helm-template.yaml
kustomize build .
- name: helm template spanner
run: |
# Test related to https://medium.com/google-cloud/f7248e077339
cd helm-chart/
SPANNER_CONNECTION_STRING=projects/PROJECT_ID/instances/SPANNER_INSTANCE_NAME/databases/SPANNER_DATABASE_NAME
SPANNER_DB_USER_GSA_ID=spanner-db-user@my-project.iam.gserviceaccount.com
helm template . \
--set cartDatabase.inClusterRedis.create=false \
--set cartDatabase.type=spanner \
--set cartDatabase.connectionString=${SPANNER_CONNECTION_STRING} \
--set serviceAccounts.create=true \
--set serviceAccounts.annotationsOnlyForCartservice=true \
--set "serviceAccounts.annotations.iam\.gke\.io/gcp-service-account=${SPANNER_DB_USER_GSA_ID}" \
-n onlineboutique \
> helm-template.yaml
cat helm-template.yaml
kustomize build .
- name: helm template asm
run: |
# Test related to https://medium.com/google-cloud/246119e46d53
cd helm-chart/
helm template . \
--set networkPolicies.create=true \
--set sidecars.create=true \
--set serviceAccounts.create=true \
--set authorizationPolicies.create=true \
--set frontend.externalService=false \
--set frontend.virtualService.create=true \
--set frontend.virtualService.gateway.name=asm-ingressgateway \
--set frontend.virtualService.gateway.namespace=asm-ingress \
--set frontend.virtualService.gateway.labelKey=asm \
--set frontend.virtualService.gateway.labelValue=ingressgateway \
-n onlineboutique \
> helm-template.yaml
cat helm-template.yaml
kustomize build .
- name: helm template memorystore istio tls origination
run: |
# Test related to https://medium.com/google-cloud/64b71969318d
cd helm-chart/
REDIS_IP=0.0.0.0
REDIS_PORT=7378
REDIS_CERT=dsjfgkldsjflkdsjflksdajfkldsjkfljsdaklfjaskjfakdsjfaklsdjflskadjfklasjfkls
helm template . \
--set cartDatabase.inClusterRedis.create=false \
--set cartDatabase.connectionString=${REDIS_IP}:${REDIS_PORT} \
--set cartDatabase.externalRedisTlsOrigination.enable=true \
--set cartDatabase.externalRedisTlsOrigination.certificate="${REDIS_CERT}" \
--set cartDatabase.externalRedisTlsOrigination.endpointAddress=${REDIS_IP} \
--set cartDatabase.externalRedisTlsOrigination.endpointPort=${REDIS_PORT} \
-n onlineboutique \
> helm-template.yaml
cat helm-template.yaml
kustomize build .

74
.github/workflows/install-dependencies.sh vendored Executable file
View File

@@ -0,0 +1,74 @@
#!/bin/bash
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -euo pipefail
# install wget
sudo apt install -y wget
# install dotnet CLI
sudo apt-get update
sudo apt-get install wget
wget -O - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg
sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
wget https://packages.microsoft.com/config/debian/9/prod.list
sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list
sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get install -y apt-transport-https && \
sudo apt-get update && \
sudo apt-get install -y dotnet-sdk-10.0
echo "✅ dotnet installed"
# install kubectl
sudo apt-get install -yqq kubectl git
echo "✅ kubectl installed"
# install go
wget https://golang.org/dl/go1.25.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.25.linux-amd64.tar.gz
echo 'export GOPATH=$HOME/go' >> ~/.profile
echo 'export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin' >> ~/.profile
source ~/.profile
echo "✅ golang installed"
# install build-essential (gcc, used for go test)
sudo apt install -y build-essential
# install addlicense
go install github.com/google/addlicense@latest
sudo ln -s $HOME/go/bin/addlicense /bin
# install build-essential (gcc, used for go test)
sudo apt install -y build-essential
# install skaffold
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64 && \
chmod +x skaffold && \
sudo mv skaffold /usr/local/bin
echo "✅ skaffold installed"
# install docker
sudo apt install -yqq apt-transport-https ca-certificates curl gnupg2 software-properties-common && \
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - && \
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" && \
sudo apt-get update && \
sudo apt-get install -yqq docker-ce && \
sudo usermod -aG docker ${USER}
echo "✅ docker installed, rebooting..."
# reboot for docker setup
sudo reboot

View File

@@ -0,0 +1,56 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: kubevious-manifests-ci
on:
push:
branches:
- main
paths:
- 'helm-chart/**'
- 'kustomize/**'
- '.github/workflows/kubevious-manifests-ci.yaml'
pull_request:
paths:
- 'helm-chart/**'
- 'kustomize/**'
- '.github/workflows/kubevious-manifests-ci.yaml'
permissions:
contents: read
jobs:
kubevious-manifests-ci:
runs-on: ubuntu-24.04
timeout-minutes: 1
steps:
- uses: actions/checkout@v6
- name: Validate kubernetes-manifests
id: kubernetes-manifests-validation
uses: kubevious/cli@v1.0.64
with:
manifests: kubernetes-manifests
skip_rules: container-latest-image
- name: Validate helm-chart
id: helm-chart-validation
uses: kubevious/cli@v1.0.64
with:
manifests: helm-chart
- name: Validate kustomize
id: kustomize-validation
uses: kubevious/cli@v1.0.64
with:
manifests: kustomize
skip_rules: container-latest-image

View File

@@ -0,0 +1,45 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: kustomize-build-ci
on:
push:
branches:
- main
paths:
- 'kustomize/**'
- '.github/workflows/kustomize-build-ci.yaml'
pull_request:
paths:
- 'kustomize/**'
- '.github/workflows/kustomize-build-ci.yaml'
jobs:
kustomize-build-ci:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: kustomize build base
run: |
cd kustomize/
kubectl kustomize .
# Build the different combinations of Kustomize components found in kustomize/tests.
- name: kustomize build tests
run: |
cd kustomize/tests
KUSTOMIZE_TESTS_SUBFOLDERS=$(ls -d */)
for test in $KUSTOMIZE_TESTS_SUBFOLDERS;
do
echo "## kustomize build for " + $test
kustomize build $test
done

View File

@@ -0,0 +1,37 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: terraform-validate-ci
on:
push:
branches:
- main
paths:
- 'terraform/**'
- '.github/workflows/terraform-validate-ci.yaml'
pull_request:
paths:
- 'terraform/**'
- '.github/workflows/terraform-validate-ci.yaml'
jobs:
terraform-validate-ci:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: hashicorp/setup-terraform@v3
- name: terraform init & validate
run: |
cd terraform/
terraform init -backend=false
terraform validate

28
.gitignore vendored Normal file
View File

@@ -0,0 +1,28 @@
.DS_Store
.eclipse.buildship.core.prefs
.gradle/
.idea/
.kubernetes-manifests-*/
.project
.skaffold-*.yaml
.terraform.lock.hcl
.terraform/*
.venv/
.vs/
.vscode/
*.iml
*.ipr
*.iws
*.pyc
*.swp
*.tfstate*
*.tfvars
*~
bin/
build/
Dockerfile.pip
node_modules/
obj/
pkg/
release/wi-kubernetes-manifests.yaml
vendor/

202
LICENSE Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

1
Online-Boutique Submodule

Submodule Online-Boutique added at 45a4f0ea5e

169
README.md Normal file
View File

@@ -0,0 +1,169 @@
<!-- <p align="center">
<img src="/src/frontend/static/icons/Hipster_HeroLogoMaroon.svg" width="300" alt="Online Boutique" />
</p> -->
![Continuous Integration](https://github.com/GoogleCloudPlatform/microservices-demo/workflows/Continuous%20Integration%20-%20Main/Release/badge.svg)
**Online Boutique** is a cloud-first microservices demo application. The application is a
web-based e-commerce app where users can browse items, add them to the cart, and purchase them.
Google uses this application to demonstrate how developers can modernize enterprise applications using Google Cloud products, including: [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine), [Cloud Service Mesh (CSM)](https://cloud.google.com/service-mesh), [gRPC](https://grpc.io/), [Cloud Operations](https://cloud.google.com/products/operations), [Spanner](https://cloud.google.com/spanner), [Memorystore](https://cloud.google.com/memorystore), [AlloyDB](https://cloud.google.com/alloydb), and [Gemini](https://ai.google.dev/). This application works on any Kubernetes cluster.
If youre using this demo, please **★Star** this repository to show your interest!
**Note to Googlers:** Please fill out the form at [go/microservices-demo](http://go/microservices-demo).
## Architecture
**Online Boutique** is composed of 11 microservices written in different
languages that talk to each other over gRPC.
[![Architecture of
microservices](/docs/img/architecture-diagram.png)](/docs/img/architecture-diagram.png)
Find **Protocol Buffers Descriptions** at the [`./protos` directory](/protos).
| Service | Language | Description |
| ---------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| [frontend](/src/frontend) | Go | Exposes an HTTP server to serve the website. Does not require signup/login and generates session IDs for all users automatically. |
| [cartservice](/src/cartservice) | C# | Stores the items in the user's shopping cart in Redis and retrieves it. |
| [productcatalogservice](/src/productcatalogservice) | Go | Provides the list of products from a JSON file and ability to search products and get individual products. |
| [currencyservice](/src/currencyservice) | Node.js | Converts one money amount to another currency. Uses real values fetched from European Central Bank. It's the highest QPS service. |
| [paymentservice](/src/paymentservice) | Node.js | Charges the given credit card info (mock) with the given amount and returns a transaction ID. |
| [shippingservice](/src/shippingservice) | Go | Gives shipping cost estimates based on the shopping cart. Ships items to the given address (mock) |
| [emailservice](/src/emailservice) | Python | Sends users an order confirmation email (mock). |
| [checkoutservice](/src/checkoutservice) | Go | Retrieves user cart, prepares order and orchestrates the payment, shipping and the email notification. |
| [recommendationservice](/src/recommendationservice) | Python | Recommends other products based on what's given in the cart. |
| [adservice](/src/adservice) | Java | Provides text ads based on given context words. |
| [loadgenerator](/src/loadgenerator) | Python/Locust | Continuously sends requests imitating realistic user shopping flows to the frontend. |
## Screenshots
| Home Page | Checkout Screen |
| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| [![Screenshot of store homepage](/docs/img/online-boutique-frontend-1.png)](/docs/img/online-boutique-frontend-1.png) | [![Screenshot of checkout screen](/docs/img/online-boutique-frontend-2.png)](/docs/img/online-boutique-frontend-2.png) |
## Quickstart (GKE)
1. Ensure you have the following requirements:
- [Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project).
- Shell environment with `gcloud`, `git`, and `kubectl`.
2. Clone the latest major version.
```sh
git clone --depth 1 --branch v0 https://github.com/GoogleCloudPlatform/microservices-demo.git
cd microservices-demo/
```
The `--depth 1` argument skips downloading git history.
3. Set the Google Cloud project and region and ensure the Google Kubernetes Engine API is enabled.
```sh
export PROJECT_ID=<PROJECT_ID>
export REGION=us-central1
gcloud services enable container.googleapis.com \
--project=${PROJECT_ID}
```
Substitute `<PROJECT_ID>` with the ID of your Google Cloud project.
4. Create a GKE cluster and get the credentials for it.
```sh
gcloud container clusters create-auto online-boutique \
--project=${PROJECT_ID} --region=${REGION}
```
Creating the cluster may take a few minutes.
5. Deploy Online Boutique to the cluster.
```sh
kubectl apply -f ./release/kubernetes-manifests.yaml
```
6. Wait for the pods to be ready.
```sh
kubectl get pods
```
After a few minutes, you should see the Pods in a `Running` state:
```
NAME READY STATUS RESTARTS AGE
adservice-76bdd69666-ckc5j 1/1 Running 0 2m58s
cartservice-66d497c6b7-dp5jr 1/1 Running 0 2m59s
checkoutservice-666c784bd6-4jd22 1/1 Running 0 3m1s
currencyservice-5d5d496984-4jmd7 1/1 Running 0 2m59s
emailservice-667457d9d6-75jcq 1/1 Running 0 3m2s
frontend-6b8d69b9fb-wjqdg 1/1 Running 0 3m1s
loadgenerator-665b5cd444-gwqdq 1/1 Running 0 3m
paymentservice-68596d6dd6-bf6bv 1/1 Running 0 3m
productcatalogservice-557d474574-888kr 1/1 Running 0 3m
recommendationservice-69c56b74d4-7z8r5 1/1 Running 0 3m1s
redis-cart-5f59546cdd-5jnqf 1/1 Running 0 2m58s
shippingservice-6ccc89f8fd-v686r 1/1 Running 0 2m58s
```
7. Access the web frontend in a browser using the frontend's external IP.
```sh
kubectl get service frontend-external | awk '{print $4}'
```
Visit `http://EXTERNAL_IP` in a web browser to access your instance of Online Boutique.
8. Congrats! You've deployed the default Online Boutique. To deploy a different variation of Online Boutique (e.g., with Google Cloud Operations tracing, Istio, etc.), see [Deploy Online Boutique variations with Kustomize](#deploy-online-boutique-variations-with-kustomize).
9. Once you are done with it, delete the GKE cluster.
```sh
gcloud container clusters delete online-boutique \
--project=${PROJECT_ID} --region=${REGION}
```
Deleting the cluster may take a few minutes.
## Additional deployment options
- **Terraform**: [See these instructions](/terraform) to learn how to deploy Online Boutique using [Terraform](https://www.terraform.io/intro).
- **Istio / Cloud Service Mesh**: [See these instructions](/kustomize/components/service-mesh-istio/README.md) to deploy Online Boutique alongside an Istio-backed service mesh.
- **Non-GKE clusters (Minikube, Kind, etc)**: See the [Development guide](/docs/development-guide.md) to learn how you can deploy Online Boutique on non-GKE clusters.
- **AI assistant using Gemini**: [See these instructions](/kustomize/components/shopping-assistant/README.md) to deploy a Gemini-powered AI assistant that suggests products to purchase based on an image.
- **And more**: The [`/kustomize` directory](/kustomize) contains instructions for customizing the deployment of Online Boutique with other variations.
## Documentation
- [Development](/docs/development-guide.md) to learn how to run and develop this app locally.
## Demos featuring Online Boutique
- [Security hardening of the OnlineBoutique sample apps with the Docker Hardened Images (DHI)](https://medium.com/google-cloud/security-hardening-of-the-onlineboutique-sample-apps-with-docker-hardened-images-dhi-ca1fad348343)
- [alpine, distroless or scratch?](https://medium.com/google-cloud/alpine-distroless-or-scratch-caac35250e0b)
- [Platform Engineering in action: Deploy the Online Boutique sample apps with Score and Humanitec](https://medium.com/p/d99101001e69)
- [The new Kubernetes Gateway API with Istio and Anthos Service Mesh (ASM)](https://medium.com/p/9d64c7009cd)
- [Use Azure Redis Cache with the Online Boutique sample on AKS](https://medium.com/p/981bd98b53f8)
- [Sail Sharp, 8 tips to optimize and secure your .NET containers for Kubernetes](https://medium.com/p/c68ba253844a)
- [Deploy multi-region application with Anthos and Google cloud Spanner](https://medium.com/google-cloud/a2ea3493ed0)
- [Use Google Cloud Memorystore (Redis) with the Online Boutique sample on GKE](https://medium.com/p/82f7879a900d)
- [Use Helm to simplify the deployment of Online Boutique, with a Service Mesh, GitOps, and more!](https://medium.com/p/246119e46d53)
- [How to reduce microservices complexity with Apigee and Anthos Service Mesh](https://cloud.google.com/blog/products/application-modernization/api-management-and-service-mesh-go-together)
- [gRPC health probes with Kubernetes 1.24+](https://medium.com/p/b5bd26253a4c)
- [Use Google Cloud Spanner with the Online Boutique sample](https://medium.com/p/f7248e077339)
- [Seamlessly encrypt traffic from any apps in your Mesh to Memorystore (redis)](https://medium.com/google-cloud/64b71969318d)
- [Strengthen your app's security with Cloud Service Mesh and Anthos Config Management](https://cloud.google.com/service-mesh/docs/strengthen-app-security)
- [From edge to mesh: Exposing service mesh applications through GKE Ingress](https://cloud.google.com/architecture/exposing-service-mesh-apps-through-gke-ingress)
- [Take the first step toward SRE with Cloud Operations Sandbox](https://cloud.google.com/blog/products/operations/on-the-road-to-sre-with-cloud-operations-sandbox)
- [Deploying the Online Boutique sample application on Cloud Service Mesh](https://cloud.google.com/service-mesh/docs/onlineboutique-install-kpt)
- [Anthos Service Mesh Workshop: Lab Guide](https://codelabs.developers.google.com/codelabs/anthos-service-mesh-workshop)
- [KubeCon EU 2019 - Reinventing Networking: A Deep Dive into Istio's Multicluster Gateways - Steve Dake, Independent](https://youtu.be/-t2BfT59zJA?t=982)
- Google Cloud Next'18 SF
- [Day 1 Keynote](https://youtu.be/vJ9OaAqfxo4?t=2416) showing GKE On-Prem
- [Day 3 Keynote](https://youtu.be/JQPOPV_VH5w?t=815) showing Stackdriver
APM (Tracing, Code Search, Profiler, Google Cloud Build)
- [Introduction to Service Management with Istio](https://www.youtube.com/watch?v=wCJrdKdD6UM&feature=youtu.be&t=586)
- [Google Cloud Next'18 London Keynote](https://youtu.be/nIq2pkNcfEI?t=3071)
showing Stackdriver Incident Response Management
- [Microservices demo showcasing Go Micro](https://github.com/go-micro/demo)

43
cloudbuild.yaml Normal file
View File

@@ -0,0 +1,43 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# [START cloudbuild_microservice_demo_cloudbuild]
# This configuration file is used to build and deploy the app into a
# GKE cluster using Google Cloud Build.
#
# PREREQUISITES:
# - Cloud Build service account must have role: "Kubernetes Engine Developer"
# USAGE:
# GCP zone and GKE target cluster must be specified as substitutions
# Example invocation:
# `gcloud builds submit --config=cloudbuild.yaml --substitutions=_ZONE=us-central1-b,_CLUSTER=demo-app-staging .`
steps:
- id: 'Deploy application to cluster'
name: 'gcr.io/k8s-skaffold/skaffold:v2.16.1'
entrypoint: 'bash'
args:
- '-c'
- >
gcloud container clusters get-credentials --zone=$_ZONE $_CLUSTER;
skaffold run -f=skaffold.yaml --default-repo=gcr.io/$PROJECT_ID;
# Add more power, and more time, for heavy Skaffold build
timeout: '3600s'
options:
machineType: 'N1_HIGHCPU_8'
# [END cloudbuild_microservice_demo_cloudbuild]

View File

@@ -0,0 +1,61 @@
# Adding a new microservice
This document outlines the steps required to add a new microservice to the Online Boutique application.
## 1. Create a new directory
Create a new directory for your microservice within the `src/` directory. The directory name should be the name of your microservice.
## 2. Add source code
Place your microservice's source code inside the newly created directory. The structure of this directory should follow the conventions of the existing microservices. For example, a Python-based service would include at minimum the following files:
- `README.md`: The service's description and documentation.
- `main.py`: The application's entry point.
- `requirements.in`: A list of Python dependencies.
- `Dockerfile`: To containerize the application.
Take a look at existing microservices for inspiration.
## 3. Create a Dockerfile
Create a `Dockerfile` in your microservice's directory. This file will define the steps to build a container image for your service.
Refer to this example and tweak based on your new service's needs: https://github.com/GoogleCloudPlatform/microservices-demo/blob/main/src/frontend/Dockerfile
## 4. Create Kubernetes manifests
Create a new directory under `kustomize/components/` in the root of the repository for your microservice. Inside this directory, add the necessary Kubernetes YAML files for your new microservice. This typically includes:
- A **Deployment** to manage your service's pods.
- A **Service** to expose your microservice to other services within the cluster.
Ensure you follow the existing naming conventions and that the container image specified in the Deployment matches the one built by your `cloudbuild.yaml` and `skaffold.yaml` files.
Refer to this example and tweak based on your new service's needs: https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/kustomize/components/shopping-assistant
## 5. Update the root `kustomization.yaml` file
Add your newly created component to the root kustomization file so it gets picked up by the deployment cycle.
The file is available here: https://github.com/GoogleCloudPlatform/microservices-demo/blob/main/kustomize/kustomization.yaml
## 6. Update the root `skaffold.yaml`
Add your newly created service to the root skaffold file so the images build correctly.
The file is available here: https://github.com/GoogleCloudPlatform/microservices-demo/blob/main/skaffold.yaml
## 7. Update the Helm chart
Add your newly created service to the Helm chart templates and default values.
The chart is available here: https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/helm-chart
## 8. Update the documentation
Finally, update the project's documentation to reflect the addition of your new microservice. This may include:
- Adding a section to the main `README.md` if the service introduces significant new functionality.
- Updating the architecture diagrams in the `docs/img` directory.
- Adding a new document in the `docs` directory if the service requires detailed explanation.

106
docs/cloudshell-tutorial.md Normal file
View File

@@ -0,0 +1,106 @@
# Online Boutique quickstart
This tutorial shows you how to deploy **[Online Boutique](https://github.com/GoogleCloudPlatform/microservices-demo)** to a Kubernetes cluster.
You'll be able to run Online Boutique on:
- a local **[minikube](https://minikube.sigs.k8s.io/docs/)** cluster, which comes built in to the Cloud Shell instance
- a **[Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine)** cluster using a new or existing [Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project)
Let's get started!
## Kubernetes cluster setup
Set up a Kubernetes cluster using the instructions below for either **minikube** or **GKE**.
### Minikube instructions
Minikube creates a local Kubernetes cluster on Cloud Shell.
1. Click <walkthrough-editor-spotlight spotlightId="minikube-status-bar">minikube</walkthrough-editor-spotlight> on the status bar located at the bottom of the editor window.
2. The command palette will prompt you to choose which minikube cluster to control. Select **minikube** and, in the next prompt, click **Start** if the cluster has not already been started.
3. If prompted, authorize Cloud Shell to make a GCP API call with your credentials.
*It may take a few minutes for minikube to finish starting.*
Once minikube has started, you're ready to move on to the next step.
### GKE instructions
In order to create a GKE cluster, you'll need to **[create a Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project)** or use an existing project.
1. Access the command palette by going to **View > Find Command**.
2. Run the command **"Cloud Code: Create GKE cluster"**.
3. Select your GCP project.
4. Apply the following configurations in the GKE wizard:
> - Zone: us-central1-b
> - Cluster name: onlineboutique
> - Node count: 4
> - Machine type: e2-standard-2
5. Click **Create Cluster**. Once your cluster has been created successfully, you can move on to the next step.
## Run on Kubernetes
Now you can run Online Boutique on your Kubernetes cluster!
1. Launch the <walkthrough-editor-spotlight spotlightId="cloud-code-status-bar">Cloud Code menu</walkthrough-editor-spotlight> from the status bar and select <walkthrough-editor-spotlight spotlightId="cloud-code-run-on-k8s">Run on Kubernetes</walkthrough-editor-spotlight>.
2. If prompted to select a Skaffold Profile, select **[default]**.
3. Select **Yes** to confirm your current context.
4. If you're using a GKE cluster, you'll need to confirm your container image registry.
5. If prompted, authorize Cloud Shell to make a GCP API call with your credentials.
Cloud Code uses configurations defined in <walkthrough-editor-open-file filePath="skaffold.yaml">skaffold.yaml</walkthrough-editor-open-file> to build and deploy the app. *It may take a few minutes for the deploy to complete.*
6. Once the app is running, the local URLs will be displayed in the <walkthrough-editor-spotlight spotlightId="output">Output</walkthrough-editor-spotlight> terminal.
7. To access your Online Boutique frontend service, click on the <walkthrough-spotlight-pointer spotlightId="devshell-web-preview-button" target="cloudshell">Web Preview button</walkthrough-spotlight-pointer> in the upper right of the editor window.
8. Select **Change Port** and enter '4503' as the port, then click **Change and Preview**. Your app will open in a new window.
## Stop the app
To stop running the app:
1. Go to the <walkthrough-editor-spotlight spotlightId="activity-bar-debug">Debug view</walkthrough-editor-spotlight>
2. Click the **Stop** icon.
3. Select **Yes** to clean up deployed resources.
You can start, stop, and debug apps from the Debug view.
### Clean up
If you've deployed your app to a GKE cluster in your Google Cloud project, you'll want to delete the cluster to avoid incurring charges.
1. Navigate to the <walkthrough-editor-spotlight spotlightId="activity-bar-cloud-k8s">Cloud Code - Kubernetes view</walkthrough-editor-spotlight> in the Activity bar.
2. Under the <walkthrough-editor-spotlight spotlightId="cloud-code-gke-explorer">Google Kubernetes Engine Explorer tab</walkthrough-editor-spotlight>, right-click on your cluster and select **Delete Cluster**.
## Conclusion
<walkthrough-conclusion-trophy></walkthrough-conclusion-trophy>
Congratulations! You've successfully deployed Online Boutique using Cloud Shell.
<walkthrough-inline-feedback></walkthrough-inline-feedback>
##### What's next?
Try other deployment options for Online Boutique:
- **Istio/Cloud Service Mesh**: <walkthrough-editor-open-file filePath="./kustomize/components/service-mesh-istio/README.md">See these instructions</walkthrough-editor-open-file>.
Learn more about the [Cloud Shell](https://cloud.google.com/shell) IDE environment and the [Cloud Code](https://cloud.google.com/code) extension.

12
docs/deploystack.md Normal file
View File

@@ -0,0 +1,12 @@
## Deploy Online Boutique with DeployStack
The "Open in Google Cloud Shell" button below will use [DeployStack](https://cloud.google.com/shell/docs/cloud-shell-tutorials/deploystack/overview) to deploy Online Boutique to a new Google Kubernetes Engine (GKE) cluster.
<!-- TODO: remove reference to the deploystack-enable branch when it pushes to main -->
<a href="https://ssh.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Fmicroservices-demo&shellonly=true&cloudshell_image=gcr.io/ds-artifacts-cloudshell/deploystack_custom_image" target="_new">
<img alt="Open in Cloud Shell" src="https://gstatic.com/cloudssh/images/open-btn.svg">
</a>
The button will open up a [Cloud Shell](https://cloud.google.com/shell) session where you will select your Google Cloud project. After project selection, the following will happen automatically:
1. a GKE cluster will be created inside the select project
2. Online Boutique (and its load generator) will be deployed to that cluster

131
docs/development-guide.md Normal file
View File

@@ -0,0 +1,131 @@
# Development Guide
This doc explains how to build and run the Online Boutique source code locally using the `skaffold` command-line tool.
## Prerequisites
- [Docker for Desktop](https://www.docker.com/products/docker-desktop)
- [kubectl](https://kubernetes.io/docs/tasks/tools/) (can be installed via `gcloud components install kubectl` for Option 1 - GKE)
- [skaffold **2.0.2+**](https://skaffold.dev/docs/install/) (latest version recommended), a tool that builds and deploys Docker images in bulk.
- Clone the repository.
```sh
git clone https://github.com/GoogleCloudPlatform/microservices-demo
cd microservices-demo/
```
- A Google Cloud project with Google Container Registry enabled. (for Option 1 - GKE)
- [Minikube](https://minikube.sigs.k8s.io/docs/start/) (optional for Option 2 - Local Cluster)
- [Kind](https://kind.sigs.k8s.io/) (optional for Option 2 - Local Cluster)
## Option 1: Google Kubernetes Engine (GKE)
> 💡 Recommended if you're using Google Cloud and want to try it on
> a realistic cluster. **Note**: If your cluster has Workload Identity enabled,
> [see these instructions](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#enable)
1. Create a Google Kubernetes Engine cluster and make sure `kubectl` is pointing
to the cluster.
```sh
gcloud services enable container.googleapis.com
```
```sh
gcloud container clusters create-auto demo --region=us-central1
```
```
kubectl get nodes
```
2. Enable Artifact Registry (AR) on your GCP project and configure the
`docker` CLI to authenticate to AR:
```sh
gcloud services enable artifactregistry.googleapis.com
```
```sh
gcloud artifacts repositories create microservices-demo \
--repository-format=docker \
--location=us \
```
```sh
gcloud auth configure-docker -q
```
3. In the root of this repository, run:
```
skaffold run --default-repo=us-docker.pkg.dev/PROJECT_ID/microservices-demo
```
Where `PROJECT_ID` is replaced by your Google Cloud project ID.
This command:
- Builds the container images.
- Pushes them to AR.
- Applies the `./kubernetes-manifests` deploying the application to
Kubernetes.
**Troubleshooting:** If you get "No space left on device" error on Google
Cloud Shell, you can build the images on Google Cloud Build: [Enable the
Cloud Build
API](https://console.cloud.google.com/flows/enableapi?apiid=cloudbuild.googleapis.com),
then run `skaffold run -p gcb --default-repo=us-docker.pkg.dev/[PROJECT_ID]/microservices-demo` instead.
4. Find the IP address of your application, then visit the application on your
browser to confirm installation.
kubectl get service frontend-external
5. Navigate to `http://EXTERNAL-IP` to access the web frontend.
## Option 2 - Local Cluster
1. Launch a local Kubernetes cluster with one of the following tools:
- To launch **Minikube** (tested with Ubuntu Linux). Please, ensure that the
local Kubernetes cluster has at least:
- 4 CPUs
- 4.0 GiB memory
- 32 GB disk space
```shell
minikube start --cpus=4 --memory 4096 --disk-size 32g
```
- To launch **Docker for Desktop** (tested with Mac/Windows). Go to Preferences:
- choose “Enable Kubernetes”,
- set CPUs to at least 3, and Memory to at least 6.0 GiB
- on the "Disk" tab, set at least 32 GB disk space
- To launch a **Kind** cluster:
```shell
kind create cluster
```
2. Run `kubectl get nodes` to verify you're connected to the respective control plane.
3. Run `skaffold run` (first time will be slow, it can take ~20 minutes).
This will build and deploy the application. If you need to rebuild the images
automatically as you refactor the code, run `skaffold dev` command.
4. Run `kubectl get pods` to verify the Pods are ready and running.
5. Run `kubectl port-forward deployment/frontend 8080:8080` to forward a port to the frontend service.
6. Navigate to `localhost:8080` to access the web frontend.
## Adding a new microservice
In general, the set of core microservices for Online Boutique is fairly complete and unlikely to change in the future, but it can be useful to add an additional optional microservice that can be deployed to complement the core services.
See the [Adding a new microservice](adding-new-microservice.md) guide for instructions on how to add a new microservice.
## Cleanup
If you've deployed the application with `skaffold run` command, you can run
`skaffold delete` to clean up the deployed resources.

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

BIN
docs/img/memorystore.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 KiB

View File

@@ -0,0 +1,39 @@
## Product Requirements
This document contains a list of requirements that every change made to this repository should meet.
Every change must:
1. Preserve the golden user journey taken by Kubernetes beginners.
1. Preserve the simplicity of demos.
1. Preserve the simplicity of the GKE quickstart.
These requirements are about the default deployment (default configuration) of Online Boutique.
Changes that will violate any of these rules should not be built into the default configuration of Online Boutique.
Such changes should be opt-in only — ideally, as a [Kustomize Component](https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/kustomize) if they align with the [purpose of Online Boutique](/docs/purpose.md).
### 1. Preserve the golden user journey taken by Kubernetes beginners
The following statement about Online Boutique should always be true:
> A user outside of Google can deploy Online Boutique's default configuration on a [_kind_ Kubernetes cluster](https://kind.sigs.k8s.io/).
This statement describes the golden user journey that we expect new Kubernetes users to take while onboarding to Online Boutique.
Being able to run Online Boutique on a _kind_ cluster ensures that Online Boutique is free and cloud-agnostic. This is aligned with [Google's mission](https://about.google/) of making information universally accessible and useful. To be specific, Online Boutique should be useful and accessible to developers that are new to Kubernetes.
### 2. Preserve the simplicity of demos
New changes should not complicate the primary user journey showcased in live demos and tutorials.
Today, the primary user journey is as follows:
1. Visit Online Boutique on a web browser.
2. Select an item from the homepage and add the item to the cart.
3. The checkout form is pre-populated with placeholder data (e.g. the shipping address).
4. The user checks out and completes the order.
### 3. Preserve the simplicity of the GKE quickstart
New changes should not add additional complexity in the [main Online Boutique quickstart](https://github.com/GoogleCloudPlatform/microservices-demo#quickstart-gke).
In particular, new changes should not add extra required steps or additional required tools in that quickstart.
Ideally, extensions to Online Boutique's default functionality (such as a new microservice or a new cloud service integration) should be added as a [Kustomize Component](https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/kustomize/components) which users can optionally opt into.

15
docs/purpose.md Normal file
View File

@@ -0,0 +1,15 @@
## Purpose
Today, the primary purpose of Online Boutique is to demonstrate:
* [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine)
* [Anthos](https://cloud.google.com/anthos)
* [Google Cloud Operations](https://cloud.google.com/products/operations)
* tools and technologies commonly used alongside the above products
while being accessible and useful to all new Kubernetes users.
### Why does the purpose matter?
We filter and prioritize the work to be done in this repository based on the purpose defined above.
If you wish to make changes to this repository that do not align with the above purpose, we encourage you to maintain your own fork of Online Boutique.

102
docs/releasing/README.md Normal file
View File

@@ -0,0 +1,102 @@
# Releasing Online Boutique
This document walks through the process of creating a new release of Online Boutique.
## Prerequisites for tagging a release
1. Choose the logical [next release tag](https://github.com/GoogleCloudPlatform/bank-of-anthos/releases), using [semantic versioning](https://semver.org/): `vX.Y.Z`.
If this release includes significant feature changes, update the minor version (`Y`). Otherwise, for bug-fix releases or standard quarterly release, update the patch version `Z`).
2. Ensure that the following commands are in your `PATH`:
- `gsed` (found in the `gnu-sed` Brew package for macOS, or by symlinking `sed` for Linux)
- `gcloud`
- `helm`
3. Make sure that your `gcloud` is authenticated:
```sh
gcloud auth login
gcloud auth configure-docker us-central1-docker.pkg.dev
```
## Create and tag the new release
Run the `make-release.sh` script found inside the `docs/releasing/` directory:
```sh
# assuming you are inside the root path of the bank-of-anthos repository
export TAG=vX.Y.Z # This is the new version (e.g. `v0.3.5`)
export REPO_PREFIX=us-central1-docker.pkg.dev/google-samples/microservices-demo # This is the Docker repository for tagged images
export PROJECT_ID=google-samples # This is the Google Cloud project for the release CI
./docs/releasing/make-release.sh
```
This script does the following:
1. Uses `make-docker-images.sh` to build and push a Docker image for each microservice to the previously specified repository.
2. Uses `make-release-artifacts.sh` to regenerates (and update the image $TAGS) YAML file at `./release/kubernetes-manifests.yaml` and `./kustomize/base/`.
3. Runs `git tag` and pushes a new branch (e.g., `release/v0.3.5`) with the changes to `./release/kubernetes-manifests.yaml`.
You can then browse the [Container Registry repository](https://pantheon.corp.google.com/gcr/images/google-samples/global/microservices-demo?project=google-samples) to make sure a Docker image was created for each microservice (with the new version tag).
## Create the PR
Now that the release branch has been created, you can find it in the [list of branches](https://github.com/GoogleCloudPlatform/microservices-demo/branches) and create a pull request targeting `main` (the default branch).
This process is going to trigger multiple CI checks as well as stage the release onto a temporary cluster. Once the PR has been approved and all checks are successfully passing, you can then merge the branch. Make sure to include the release draft (see next section) in the pull-request description for reviewers to see.
Once reviewed and you're ready to merge, make sure to not delete the release branch or the tags during that process.
## Add notes to the release
Once the PR has been fully merged, you are ready to create a new release for the newly created [tag](https://github.com/GoogleCloudPlatform/microservices-demo/tags).
- Click the breadcrumbs on the row of the latest tag that was created in the [tags](https://github.com/GoogleCloudPlatform/microservices-demo/tags) page
- Select the `Create release` option
The release notes should contain a brief description of the changes since the previous release (like bug fixed and new features). For inspiration, you can look at the list of [releases](https://github.com/GoogleCloudPlatform/microservices-demo/releases).
> ***Note:*** No assets need to be uploaded. They are picked up automatically from the tagged revision
## Deploy on the production environment
Once the release notes are published, you should then replace the version of the production environment to the newly published version.
1. Connect to the [online-boutique-release GKE cluster](https://pantheon.corp.google.com/kubernetes/clusters/details/us-central1-c/online-boutique-release/details?project=online-boutique-ci):
```sh
gcloud container clusters get-credentials online-boutique-release \
--zone us-central1-c --project online-boutique-ci
```
2. Deploy `release/kubernetes-manifests.yaml` to it:
```sh
kubectl apply -f ./release/kubernetes-manifests.yaml
```
3. Remove unnecessary objects:
```sh
kubectl delete service frontend-external
kubectl delete deployment loadgenerator
```
3. Make sure [cymbal-shops.retail.cymbal.dev](https://cymbal-shops.retail.cymbal.dev) works.
## Update major tags
1. Update the relevant major tag (for example, `v1`):
```sh
export MAJOR_TAG=v0 # Edit this as needed (to v1/v2/v3/etc)
git checkout release/${TAG}
git pull
git push --delete origin ${MAJOR_TAG} # Delete the remote tag (if it exists)
git tag --delete ${MAJOR_TAG} # Delete the local tag (if it exists)
git tag -a ${MAJOR_TAG} -m "Updating ${MAJOR_TAG} to its most recent release: ${TAG}"
git push origin ${MAJOR_TAG} # Push the new tag to origin
```
## Announce the new release internally
Once the new release is out, you can now announce it via [g/online-boutique-announce](https://groups.google.com/a/google.com/g/online-boutique-announce).

View File

@@ -0,0 +1,13 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Builds and pushes docker image for each demo microservice.
set -euo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT=$SCRIPT_DIR/../..
log() { echo "$1" >&2; }
TAG="${TAG:?TAG env variable must be specified}"
REPO_PREFIX="${REPO_PREFIX:?REPO_PREFIX env variable must be specified}"
PROJECT_ID="${PROJECT_ID:?PROJECT_ID env variable must be specified e.g. google-samples}"
while IFS= read -d $'\0' -r dir; do
# build image
svcname="$(basename "${dir}")"
builddir="${dir}"
#PR 516 moved cartservice build artifacts one level down to src
if [ $svcname == "cartservice" ]
then
builddir="${dir}/src"
fi
image="${REPO_PREFIX}/$svcname:$TAG"
image_with_sample_public_image_tag="${REPO_PREFIX}/$svcname:sample-public-image-$TAG"
(
cd "${builddir}"
log "Building (and pushing) image on Google Cloud Build: ${image}"
gcloud builds submit --project=${PROJECT_ID} --tag=${image}
gcloud artifacts docker tags add ${image} ${image_with_sample_public_image_tag}
)
done < <(find "${REPO_ROOT}/src" -mindepth 1 -maxdepth 1 -type d -print0)
log "Successfully built and pushed all images."

View File

@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Packages and pushes Online Boutique's Helm chart in public Artifact Registry.
set -euo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT=$SCRIPT_DIR/../..
log() { echo "$1" >&2; }
TAG="${TAG:?TAG env variable must be specified}"
HELM_CHART_REPO="us-docker.pkg.dev/online-boutique-ci/charts"
cd ${REPO_ROOT}/helm-chart
gsed -i "s/^appVersion:.*/appVersion: \"${TAG}\"/" Chart.yaml
gsed -i "s/^version:.*/version: ${TAG:1}/" Chart.yaml
helm package .
helm push onlineboutique-${TAG:1}.tgz oci://$HELM_CHART_REPO
rm ./onlineboutique-${TAG:1}.tgz
log "Successfully built and pushed the Helm chart."

View File

@@ -0,0 +1,137 @@
#!/usr/bin/env bash
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This script compiles manifest files with the image tags and places them in
# /release/...
set -euo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT=$SCRIPT_DIR/../..
[[ -n "${DEBUG:-}" ]] && set -x
log() { echo "$1" >&2; }
TAG="${TAG:?TAG env variable must be specified}"
REPO_PREFIX="${REPO_PREFIX:?REPO_PREFIX env variable must be specified}"
OUT_DIR="${OUT_DIR:-${REPO_ROOT}/release}"
print_license_header() {
cat "${SCRIPT_DIR}/license_header.txt"
echo
}
print_autogenerated_warning() {
cat<<EOF
# ----------------------------------------------------------
# WARNING: This file is autogenerated. Do not manually edit.
# ----------------------------------------------------------
EOF
}
# define gsed as a function on Linux for compatibility
[ "$(uname -s)" == "Linux" ] && gsed() {
sed "$@"
}
read_manifests_except_kustomization() {
local dir
dir="$1"
while IFS= read -d $'\0' -r file; do
echo "---"
# strip license headers (pattern "^# ")
awk '
/^[^# ]/ { found = 1 }
found { print }' "${file}"
done < <(find "${dir}" -name '*.yaml' ! -name 'kustomization.yaml' -type f -print0)
}
mk_kubernetes_manifests() {
out_manifest="$(read_manifests_except_kustomization "${REPO_ROOT}/kubernetes-manifests")"
# replace "image" repo, tag for each service
for dir in ./src/*/
do
svcname="$(basename "${dir}")"
image="$REPO_PREFIX/$svcname:$TAG"
pattern="^(\s*)image:\s.*$svcname(.*)(\s*)"
replace="\1image: $image\3"
out_manifest="$(gsed -r "s|$pattern|$replace|g" <(echo "${out_manifest}") )"
done
print_license_header
print_autogenerated_warning
echo '# [START gke_release_kubernetes_manifests_microservices_demo]'
echo "${out_manifest}"
echo "# [END gke_release_kubernetes_manifests_microservices_demo]"
}
mk_istio_manifests() {
print_license_header
print_autogenerated_warning
echo '# [START servicemesh_release_istio_manifests_microservices_demo]'
# This just copies the yaml from the component (excluding kustomization.yaml)
# since there is no easy way to render individual kustomize component resources
read_manifests_except_kustomization "${REPO_ROOT}/kustomize/components/service-mesh-istio/"
echo '# [END servicemesh_release_istio_manifests_microservices_demo]'
}
mk_kustomize_base() {
for file_to_copy in ./kubernetes-manifests/*.yaml
do
# Don't copy kustomization.yaml.
if [[ $file_to_copy == "./kubernetes-manifests/kustomization.yaml" ]]; then
continue
fi
cp ${file_to_copy} ./kustomize/base/
service_name="$(basename "${file_to_copy}" .yaml)"
image="$REPO_PREFIX/$service_name:$TAG"
# Inside redis.yaml, we use the official `redis:alpine` Docker image.
# We don't use an image from `us-central1-docker.pkg.dev/google-samples/microservices-demo`.
if [[ $service_name == "redis" ]]; then
continue
fi
pattern="^(\s*)image:\s.*${service_name}(.*)(\s*)"
replace="\1image: ${image}\3"
gsed --in-place --regexp-extended "s|${pattern}|${replace}|g" ./kustomize/base/${service_name}.yaml
done
}
main() {
mkdir -p "${OUT_DIR}"
local k8s_manifests_file istio_manifests_file
k8s_manifests_file="${OUT_DIR}/kubernetes-manifests.yaml"
mk_kubernetes_manifests > "${k8s_manifests_file}"
log "Written ${k8s_manifests_file}"
istio_manifests_file="${OUT_DIR}/istio-manifests.yaml"
mk_istio_manifests > "${istio_manifests_file}"
log "Written ${istio_manifests_file}"
mk_kustomize_base
log "Written Kustomize base"
}
main

69
docs/releasing/make-release.sh Executable file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This script creates a new release by:
# - 1. building/pushing images
# - 2. injecting tags into YAML manifests
# - 3. creating a new git tag
# - 4. pushing the tag/commit to main.
set -euo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT=$SCRIPT_DIR/../..
[[ -n "${DEBUG:-}" ]] && set -x
log() { echo "$1" >&2; }
fail() { log "$1"; exit 1; }
TAG="${TAG:?TAG env variable must be specified}"
REPO_PREFIX="${REPO_PREFIX:?REPO_PREFIX env variable must be specified e.g. us-central1-docker.pkg.dev\/google-samples\/microservices-demo}"
PROJECT_ID="${PROJECT_ID:?PROJECT_ID env variable must be specified e.g. google-samples}"
if [[ "$TAG" != v* ]]; then
fail "\$TAG must start with 'v', e.g. v0.1.0 (got: $TAG)"
fi
# ensure there are no uncommitted changes
if [[ $(git status -s | wc -l) -gt 0 ]]; then
echo "error: can't have uncommitted changes"
exit 1
fi
# make sure local source is up to date
git checkout main
git pull
# build and push images
"${SCRIPT_DIR}"/make-docker-images.sh
# update yaml
"${SCRIPT_DIR}"/make-release-artifacts.sh
# build and push images
"${SCRIPT_DIR}"/make-helm-chart.sh
# create git release / push to new branch
git checkout -b "release/${TAG}"
git add "${REPO_ROOT}/release/"
git add "${REPO_ROOT}/kustomize/base/"
git add "${REPO_ROOT}/helm-chart/"
git commit --allow-empty -m "Release $TAG"
log "Pushing k8s manifests to release/${TAG}..."
git tag "$TAG"
git push --set-upstream origin "release/${TAG}"
git push --tags
log "Successfully tagged release $TAG."

38
helm-chart/Chart.yaml Normal file
View File

@@ -0,0 +1,38 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: v2
name: onlineboutique
description: A Helm chart for Kubernetes for Online Boutique
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.10.4
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "v0.10.4"

38
helm-chart/README.md Normal file
View File

@@ -0,0 +1,38 @@
# Helm chart for Online Boutique
If you'd like to deploy Online Boutique via its Helm chart, you could leverage the following instructions.
**Warning:** Online Boutique's Helm chart is currently experimental. If you have feedback or run into issues, let us know inside [GitHub Issue #1319](https://github.com/GoogleCloudPlatform/microservices-demo/issues/1319) or by creating a [new GitHub Issue](https://github.com/GoogleCloudPlatform/microservices-demo/issues/new/choose).
Deploy the default setup of Online Boutique:
```sh
helm upgrade onlineboutique oci://us-docker.pkg.dev/online-boutique-ci/charts/onlineboutique \
--install
```
Deploy advanced scenario of Online Boutique:
```sh
helm upgrade onlineboutique oci://us-docker.pkg.dev/online-boutique-ci/charts/onlineboutique \
--install \
--create-namespace \
--set images.repository=us-docker.pkg.dev/my-project/microservices-demo \
--set frontend.externalService=false \
--set redis.create=false \
--set cartservice.database.type=spanner \
--set cartservice.database.connectionString=projects/my-project/instances/onlineboutique/databases/carts \
--set serviceAccounts.create=true \
--set authorizationPolicies.create=true \
--set networkPolicies.create=true \
--set sidecars.create=true \
--set frontend.virtualService.create=true \
--set 'serviceAccounts.annotations.iam\.gke\.io/gcp-service-account=spanner-db-user@my-project.iam.gserviceaccount.com' \
--set serviceAccounts.annotationsOnlyForCartservice=true \
-n onlineboutique
```
For the full list of configurations, see [values.yaml](./values.yaml).
You could also find advanced scenarios with these blogs below:
- [Online Boutique samples Helm chart, to simplify the setup of advanced and secured scenarios with Service Mesh and GitOps](https://medium.com/google-cloud/246119e46d53)
- [gRPC health probes with Kubernetes 1.24+](https://medium.com/google-cloud/b5bd26253a4c)
- [Use Google Cloud Spanner with the Online Boutique sample](https://medium.com/google-cloud/f7248e077339)

View File

@@ -0,0 +1,15 @@
{{- if and .Values.frontend.create .Values.frontend.externalService }}
Note: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status of the frontend IP address with:
kubectl get --namespace {{ .Release.Namespace }} svc -w {{ .Values.frontend.name }}-external
Get the external IP address of the frontend:
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ .Values.frontend.name }}-external --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP
{{- end }}
{{- if .Values.frontend.virtualService.create }}
Get the external IP address of the ingress gateway:
export SERVICE_IP=$(kubectl get svc --namespace {{ .Values.frontend.virtualService.gateway.namespace }} {{ .Values.frontend.virtualService.gateway.name }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP
{{- end }}

View File

@@ -0,0 +1,178 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.adService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.adService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.adService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.adService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.adService.name }}
template:
metadata:
labels:
app: {{ .Values.adService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.adService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.adService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 9555
env:
- name: PORT
value: "9555"
resources:
{{- toYaml .Values.adService.resources | nindent 10 }}
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 15
grpc:
port: 9555
livenessProbe:
initialDelaySeconds: 20
periodSeconds: 15
grpc:
port: 9555
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.adService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.adService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.adService.name }}
ports:
- name: grpc
port: 9555
targetPort: 9555
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.adService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.adService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
ports:
- port: 9555
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.adService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.adService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.adService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.adService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.AdService/GetAds
methods:
- POST
ports:
- "9555"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,405 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.cartService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.cartService.name }}
namespace: {{.Release.Namespace}}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.cartService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.cartService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.cartService.name }}
template:
metadata:
{{- if .Values.cartDatabase.externalRedisTlsOrigination.enable }}
annotations:
sidecar.istio.io/userVolumeMount: '[{"name": "{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}", "mountPath": "/etc/certs", "readonly": true}]'
sidecar.istio.io/userVolume: '[{"name": "{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}", "secret": {"secretName": "{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}"}}]'
proxy.istio.io/config: '{"holdApplicationUntilProxyStarts": true}'
{{- end }}
labels:
app: {{ .Values.cartService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.cartService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- end }}
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.cartService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 7070
env:
{{- if eq .Values.cartDatabase.type "spanner" }}
- name: SPANNER_CONNECTION_STRING
{{- else }}
- name: REDIS_ADDR
{{- end }}
value: {{ .Values.cartDatabase.connectionString | quote }}
resources:
{{- toYaml .Values.cartService.resources | nindent 10 }}
readinessProbe:
initialDelaySeconds: 15
grpc:
port: 7070
livenessProbe:
initialDelaySeconds: 15
periodSeconds: 10
grpc:
port: 7070
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.cartService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.cartService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.cartService.name }}
ports:
- name: grpc
port: 7070
targetPort: 7070
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.cartService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.cartService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
ports:
- port: 7070
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.cartService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.cartService.name }}
egress:
- hosts:
- istio-system/*
{{- if eq .Values.cartDatabase.type "redis" }}
{{- if .Values.cartDatabase.externalRedisTlsOrigination.enable }}
- ./{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}.{{ .Release.Namespace }}
{{- else }}
- ./{{ .Values.cartDatabase.inClusterRedis.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.cartService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.cartService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.CartService/AddItem
- /hipstershop.CartService/GetCart
- /hipstershop.CartService/EmptyCart
methods:
- POST
ports:
- "7070"
{{- end }}
{{- if .Values.cartDatabase.inClusterRedis.create }}
---
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
template:
metadata:
labels:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.cartDatabase.inClusterRedis.name }}
{{- else }}
serviceAccountName: default
{{- end }}
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: redis
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
{{- if .Values.cartDatabase.inClusterRedis.publicRepository }}
image: redis:alpine@sha256:4eec4565e45aa0b3966554c866bc73211e281b0b3d89fe9a33c982e6faca809d
{{- else }}
image: {{ .Values.images.repository }}/redis:alpine
{{- end }}
ports:
- containerPort: 6379
readinessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
livenessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
volumeMounts:
- mountPath: /data
name: redis-data
resources:
limits:
memory: 256Mi
cpu: 125m
requests:
cpu: 70m
memory: 200Mi
volumes:
- name: redis-data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{ .Release.Namespace }}
spec:
type: ClusterIP
selector:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
ports:
- name: tcp-redis
port: 6379
targetPort: 6379
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.cartService.name }}
ports:
- port: 6379
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
egress:
- hosts:
- istio-system/*
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.cartService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
ports:
- "6379"
{{- end }}
{{- end }}
{{- if .Values.cartDatabase.externalRedisTlsOrigination.enable }}
---
apiVersion: v1
data:
{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}.pem: {{ .Values.cartDatabase.externalRedisTlsOrigination.certificate | b64enc | quote }}
kind: Secret
metadata:
name: {{ .Values.cartDatabase.externalRedisTlsOrigination.name }}
namespace: {{ .Release.Namespace }}
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: {{ .Values.cartDatabase.externalRedisTlsOrigination.name }}
namespace: {{ .Release.Namespace }}
spec:
exportTo:
- '.'
host: {{ .Values.cartDatabase.externalRedisTlsOrigination.name }}.{{ .Release.Namespace }}
trafficPolicy:
tls:
mode: SIMPLE
caCertificates: /etc/certs/{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}.pem
---
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: {{ .Values.cartDatabase.externalRedisTlsOrigination.name }}
namespace: {{ .Release.Namespace }}
spec:
hosts:
- {{ .Values.cartDatabase.externalRedisTlsOrigination.name }}.{{ .Release.Namespace }}
addresses:
- {{ .Values.cartDatabase.externalRedisTlsOrigination.endpointAddress }}/32
endpoints:
- address: {{ .Values.cartDatabase.externalRedisTlsOrigination.endpointAddress }}
location: MESH_EXTERNAL
resolution: STATIC
ports:
- number: {{ .Values.cartDatabase.externalRedisTlsOrigination.endpointPort }}
name: tcp-redis
protocol: TCP
{{- end }}
{{- end }}

View File

@@ -0,0 +1,205 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.checkoutService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.checkoutService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.checkoutService.name }}
template:
metadata:
labels:
app: {{ .Values.checkoutService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.checkoutService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.checkoutService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 5050
readinessProbe:
grpc:
port: 5050
livenessProbe:
grpc:
port: 5050
env:
- name: PORT
value: "5050"
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "{{ .Values.productCatalogService.name }}:3550"
- name: SHIPPING_SERVICE_ADDR
value: "{{ .Values.shippingService.name }}:50051"
- name: PAYMENT_SERVICE_ADDR
value: "{{ .Values.paymentService.name }}:50051"
- name: EMAIL_SERVICE_ADDR
value: "{{ .Values.emailService.name }}:5000"
- name: CURRENCY_SERVICE_ADDR
value: "{{ .Values.currencyService.name }}:7000"
- name: CART_SERVICE_ADDR
value: "{{ .Values.cartService.name }}:7070"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.checkoutService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if .Values.googleCloudOperations.profiler }}
- name: ENABLE_PROFILER
value: "1"
{{- end }}
resources:
{{- toYaml .Values.checkoutService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.checkoutService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.checkoutService.name }}
ports:
- name: grpc
port: 5050
targetPort: 5050
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
ports:
- port: 5050
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.checkoutService.name }}
egress:
- hosts:
- istio-system/*
- ./{{ .Values.cartService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.currencyService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.emailService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.paymentService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.productCatalogService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.shippingService.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.checkoutService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.CheckoutService/PlaceOrder
methods:
- POST
ports:
- "5050"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,35 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.networkPolicies.create }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: {{ .Release.Namespace }}
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: {{ .Release.Namespace }}
spec: {}
{{- end }}

View File

@@ -0,0 +1,194 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.currencyService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.currencyService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.currencyService.name }}
template:
metadata:
labels:
app: {{ .Values.currencyService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.currencyService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.currencyService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- name: grpc
containerPort: 7000
env:
- name: PORT
value: "7000"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.currencyService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if not .Values.googleCloudOperations.profiler }}
- name: DISABLE_PROFILER
value: "1"
{{- end }}
readinessProbe:
grpc:
port: 7000
livenessProbe:
grpc:
port: 7000
resources:
{{- toYaml .Values.currencyService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.currencyService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.currencyService.name }}
ports:
- name: grpc
port: 7000
targetPort: 7000
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.currencyService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
ports:
- port: 7000
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.currencyService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.currencyService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.CurrencyService/Convert
- /hipstershop.CurrencyService/GetSupportedCurrencies
methods:
- POST
ports:
- "7000"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,190 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.emailService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.emailService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.emailService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.emailService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.emailService.name }}
template:
metadata:
labels:
app: {{ .Values.emailService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.emailService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.emailService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.emailService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if not .Values.googleCloudOperations.profiler }}
- name: DISABLE_PROFILER
value: "1"
{{- end }}
readinessProbe:
periodSeconds: 5
grpc:
port: 8080
livenessProbe:
periodSeconds: 5
grpc:
port: 8080
resources:
{{- toYaml .Values.emailService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.emailService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.emailService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.emailService.name }}
ports:
- name: grpc
port: 5000
targetPort: 8080
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.emailService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.emailService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
ports:
- port: 8080
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.emailService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.emailService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.emailService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.emailService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.EmailService/SendOrderConfirmation
methods:
- POST
ports:
- "8080"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,285 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.frontend.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.frontend.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.frontend.name }}
spec:
selector:
matchLabels:
app: {{ .Values.frontend.name }}
template:
metadata:
labels:
app: {{ .Values.frontend.name }}
annotations:
sidecar.istio.io/rewriteAppHTTPProbers: "true"
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.frontend.name }}
{{- else }}
serviceAccountName: default
{{- end }}
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.frontend.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 8080
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8080
httpHeaders:
- name: "Cookie"
value: "shop_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8080
httpHeaders:
- name: "Cookie"
value: "shop_session-id=x-liveness-probe"
env:
- name: PORT
value: "8080"
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "{{ .Values.productCatalogService.name }}:3550"
- name: CURRENCY_SERVICE_ADDR
value: "{{ .Values.currencyService.name }}:7000"
- name: CART_SERVICE_ADDR
value: "{{ .Values.cartService.name }}:7070"
- name: RECOMMENDATION_SERVICE_ADDR
value: "{{ .Values.recommendationService.name }}:8080"
- name: SHIPPING_SERVICE_ADDR
value: "{{ .Values.shippingService.name }}:50051"
- name: CHECKOUT_SERVICE_ADDR
value: "{{ .Values.checkoutService.name }}:5050"
- name: AD_SERVICE_ADDR
value: "{{ .Values.adService.name }}:9555"
- name: SHOPPING_ASSISTANT_SERVICE_ADDR
value: "{{ .Values.shoppingAssistantService.name }}:80"
- name: ENV_PLATFORM
value: {{ .Values.frontend.platform | quote }}
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.frontend.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if .Values.googleCloudOperations.profiler }}
- name: ENABLE_PROFILER
value: "1"
{{- end }}
- name: CYMBAL_BRANDING
value: {{ .Values.frontend.cymbalBranding | quote }}
- name: ENABLE_ASSISTANT
value: {{ .Values.shoppingAssistantService.create | quote }}
- name: ENABLE_SINGLE_SHARED_SESSION
value: {{ .Values.frontend.singleSharedSession | quote }}
resources:
{{- toYaml .Values.frontend.resources | nindent 12 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.frontend.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.frontend.name }}
ports:
- name: http
port: 80
targetPort: 8080
{{- if .Values.frontend.externalService }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.frontend.name }}-external
namespace: {{ .Release.Namespace }}
spec:
type: LoadBalancer
selector:
app: {{ .Values.frontend.name }}
ports:
- name: http
port: 80
targetPort: 8080
{{- end }}
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
policyTypes:
- Ingress
- Egress
ingress:
{{- if .Values.frontend.externalService }}
- {}
{{- else }}
- from:
- podSelector:
matchLabels:
app: {{ .Values.loadGenerator.name }}
{{- if .Values.frontend.virtualService.create }}
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: {{ .Values.frontend.virtualService.gateway.namespace }}
podSelector:
matchLabels:
{{ .Values.frontend.virtualService.gateway.labelKey }}: {{ .Values.frontend.virtualService.gateway.labelValue }}
{{- end }}
ports:
- port: 8080
protocol: TCP
{{- end }}
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.frontend.name }}
egress:
- hosts:
- istio-system/*
- ./{{ .Values.adService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.cartService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.checkoutService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.currencyService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.productCatalogService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.recommendationService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.shippingService.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.frontend.name }}
rules:
{{- if .Values.frontend.externalService }}
- to:
{{- else }}
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.loadGenerator.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
{{- if .Values.frontend.virtualService.create }}
- cluster.local/ns/{{ .Values.frontend.virtualService.gateway.namespace }}/sa/{{ .Values.frontend.virtualService.gateway.name }}
{{- end }}
to:
{{- end }}
- operation:
methods:
- GET
- POST
ports:
- "8080"
{{- end }}
{{- if .Values.frontend.virtualService.create }}
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
spec:
{{- with .Values.frontend.virtualService.hosts }}
hosts:
{{- toYaml . | nindent 2 }}
{{- end }}
gateways:
- {{ .Values.frontend.virtualService.gateway.namespace }}/{{ .Values.frontend.virtualService.gateway.name }}
http:
- route:
- destination:
host: {{ .Values.frontend.name }}
port:
number: 80
{{- end }}
{{- end }}

View File

@@ -0,0 +1,156 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.loadGenerator.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.loadGenerator.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.loadGenerator.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.loadGenerator.name }}
spec:
selector:
matchLabels:
app: {{ .Values.loadGenerator.name }}
replicas: 1
template:
metadata:
labels:
app: {{ .Values.loadGenerator.name }}
annotations:
sidecar.istio.io/rewriteAppHTTPProbers: "true"
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.loadGenerator.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
restartPolicy: Always
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
{{- if .Values.loadGenerator.checkFrontendInitContainer }}
initContainers:
- command:
- /bin/sh
- -exc
- |
MAX_RETRIES=12
RETRY_INTERVAL=10
for i in $(seq 1 $MAX_RETRIES); do
echo "Attempt $i: Pinging frontend: ${FRONTEND_ADDR}..."
STATUSCODE=$(wget --server-response http://${FRONTEND_ADDR} 2>&1 | awk '/^ HTTP/{print $2}')
if [ $STATUSCODE -eq 200 ]; then
echo "Frontend is reachable."
exit 0
fi
echo "Error: Could not reach frontend - Status code: ${STATUSCODE}"
sleep $RETRY_INTERVAL
done
echo "Failed to reach frontend after $MAX_RETRIES attempts."
exit 1
name: frontend-check
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: busybox:latest@sha256:e226d6308690dbe282443c8c7e57365c96b5228f0fe7f40731b5d84d37a06839
env:
- name: FRONTEND_ADDR
value: "{{ .Values.frontend.name }}:80"
{{- end }}
containers:
- name: main
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.loadGenerator.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
env:
- name: FRONTEND_ADDR
value: "{{ .Values.frontend.name }}:80"
- name: USERS
value: "10"
- name: RATE
value: "1"
resources:
{{- toYaml .Values.loadGenerator.resources | nindent 10 }}
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.loadGenerator.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.loadGenerator.name }}
spec:
podSelector:
matchLabels:
app: {{ .Values.loadGenerator.name }}
policyTypes:
- Egress
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.loadGenerator.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.loadGenerator.name }}
egress:
- hosts:
- istio-system/*
- ./{{ .Values.frontend.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,262 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.opentelemetryCollector.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{ .Release.Namespace }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Values.opentelemetryCollector.name }}
template:
metadata:
labels:
app: {{ .Values.opentelemetryCollector.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.opentelemetryCollector.name }}
{{- else }}
serviceAccountName: default
{{- end }}
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
{{- if eq .Values.opentelemetryCollector.projectId "PROJECT_ID" }}
initContainers:
# Init container retrieves the current cloud project id from the metadata server
# and inserts it into the collector config template
# https://cloud.google.com/compute/docs/storing-retrieving-metadata
- name: otel-gateway-init
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: busybox:latest@sha256:e226d6308690dbe282443c8c7e57365c96b5228f0fe7f40731b5d84d37a06839
command:
- '/bin/sh'
- '-c'
- |
sed "s/PROJECT_ID/$(curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/project/project-id)/" /template/collector-gateway-config-template.yaml >> /conf/collector-gateway-config.yaml
volumeMounts:
- name: collector-gateway-config-template
mountPath: /template
- name: collector-gateway-config
mountPath: /conf
{{- end }}
containers:
# This gateway container will receive traces and metrics from each microservice
# and forward it to GCP
- name: otel-gateway
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
args:
- --config=/conf/collector-gateway-config.yaml
image: otel/opentelemetry-collector-contrib:0.144.0@sha256:213886eb6407af91b87fa47551c3632be1a6419ff3a5114ef1e6fc364628496f
volumeMounts:
- name: collector-gateway-config
mountPath: /conf
volumes:
# Simple ConfigMap volume with template file
- name: collector-gateway-config-template
configMap:
items:
- key: collector-gateway-config-template.yaml
path: collector-gateway-config-template.yaml
name: collector-gateway-config-template
# Create a volume to store the expanded template (with correct cloud project ID)
- name: collector-gateway-config
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{ .Release.Namespace }}
spec:
ports:
- name: grpc-otlp
port: 4317
protocol: TCP
targetPort: 4317
selector:
app: {{ .Values.opentelemetryCollector.name }}
type: ClusterIP
---
apiVersion: v1
kind: ConfigMap
metadata:
name: collector-gateway-config-template
namespace: {{ .Release.Namespace }}
# Open Telemetry Collector config
# https://opentelemetry.io/docs/collector/configuration/
data:
collector-gateway-config-template.yaml: |
receivers:
otlp:
protocols:
grpc:
processors:
exporters:
googlecloud:
project: {{ .Values.opentelemetryCollector.projectId | quote }}
service:
pipelines:
traces:
receivers: [otlp] # Receive otlp-formatted data from other collector instances
processors: []
exporters: [googlecloud] # Export traces directly to Google Cloud
metrics:
receivers: [otlp]
processors: []
exporters: [googlecloud] # Export metrics to Google Cloud
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.opentelemetryCollector.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.adService.name }}
- podSelector:
matchLabels:
app: {{ .Values.cartService.name }}
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
- podSelector:
matchLabels:
app: {{ .Values.currencyService.name }}
- podSelector:
matchLabels:
app: {{ .Values.emailService.name }}
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
- podSelector:
matchLabels:
app: {{ .Values.loadGenerator.name }}
- podSelector:
matchLabels:
app: {{ .Values.paymentService.name }}
- podSelector:
matchLabels:
app: {{ .Values.productCatalogService.name }}
- podSelector:
matchLabels:
app: {{ .Values.recommendationService.name }}
- podSelector:
matchLabels:
app: {{ .Values.shippingService.name }}
ports:
- port: 4317
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.opentelemetryCollector.name }}
egress:
- hosts:
- istio-system/*
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.opentelemetryCollector.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.adService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.cartService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.currencyService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.emailService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.loadGenerator.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.paymentService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.productCatalogService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.recommendationService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.shippingService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
ports:
- "4317"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,188 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.paymentService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.paymentService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.paymentService.name }}
template:
metadata:
labels:
app: {{ .Values.paymentService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.paymentService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.paymentService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 50051
env:
- name: PORT
value: "50051"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.paymentService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if not .Values.googleCloudOperations.profiler }}
- name: DISABLE_PROFILER
value: "1"
{{- end }}
readinessProbe:
grpc:
port: 50051
livenessProbe:
grpc:
port: 50051
resources:
{{- toYaml .Values.paymentService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.paymentService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.paymentService.name }}
ports:
- name: grpc
port: 50051
targetPort: 50051
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.paymentService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
ports:
- port: 50051
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.paymentService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.paymentService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.PaymentService/Charge
methods:
- POST
ports:
- "50051"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,199 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.productCatalogService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.productCatalogService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.productCatalogService.name }}
template:
metadata:
labels:
app: {{ .Values.productCatalogService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.productCatalogService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.productCatalogService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 3550
env:
- name: PORT
value: "3550"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.productCatalogService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if not .Values.googleCloudOperations.profiler }}
- name: DISABLE_PROFILER
value: "1"
{{- end }}
- name: EXTRA_LATENCY
value: {{ .Values.productCatalogService.extraLatency }}
readinessProbe:
grpc:
port: 3550
livenessProbe:
grpc:
port: 3550
resources:
{{- toYaml .Values.productCatalogService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.productCatalogService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.productCatalogService.name }}
ports:
- name: grpc
port: 3550
targetPort: 3550
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.productCatalogService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
- podSelector:
matchLabels:
app: {{ .Values.recommendationService.name }}
ports:
- port: 3550
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.productCatalogService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.productCatalogService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.recommendationService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.ProductCatalogService/GetProduct
- /hipstershop.ProductCatalogService/ListProducts
methods:
- POST
ports:
- "3550"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,193 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.recommendationService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.recommendationService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.recommendationService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.recommendationService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.recommendationService.name }}
template:
metadata:
labels:
app: {{ .Values.recommendationService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.recommendationService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.recommendationService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 8080
readinessProbe:
periodSeconds: 5
grpc:
port: 8080
livenessProbe:
periodSeconds: 5
grpc:
port: 8080
env:
- name: PORT
value: "8080"
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "{{ .Values.productCatalogService.name }}:3550"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.recommendationService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if not .Values.googleCloudOperations.profiler }}
- name: DISABLE_PROFILER
value: "1"
{{- end }}
resources:
{{- toYaml .Values.recommendationService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.recommendationService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.recommendationService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.recommendationService.name }}
ports:
- name: grpc
port: 8080
targetPort: 8080
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.recommendationService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.recommendationService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
ports:
- port: 8080
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.recommendationService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.recommendationService.name }}
egress:
- hosts:
- istio-system/*
- ./{{ .Values.productCatalogService.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.recommendationService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.recommendationService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.RecommendationService/ListRecommendations
methods:
- POST
ports:
- "8080"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,183 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
{{- if .Values.shippingService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.shippingService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.shippingService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.shippingService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.shippingService.name }}
template:
metadata:
labels:
app: {{ .Values.shippingService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.shippingService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.shippingService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 50051
env:
- name: PORT
value: "50051"
{{- if not .Values.googleCloudOperations.profiler }}
- name: DISABLE_PROFILER
value: "1"
{{- end }}
readinessProbe:
periodSeconds: 5
grpc:
port: 50051
livenessProbe:
grpc:
port: 50051
resources:
{{- toYaml .Values.shippingService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.shippingService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.shippingService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.shippingService.name }}
ports:
- name: grpc
port: 50051
targetPort: 50051
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.shippingService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.shippingService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
ports:
- port: 50051
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.shippingService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.shippingService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.shippingService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.shippingService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.ShippingService/GetQuote
- /hipstershop.ShippingService/ShipOrder
methods:
- POST
ports:
- "50051"
{{- end }}
{{- end }}

220
helm-chart/values.yaml Normal file
View File

@@ -0,0 +1,220 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Default values for onlineboutique.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
images:
repository: us-central1-docker.pkg.dev/google-samples/microservices-demo
# Overrides the image tag whose default is the chart appVersion.
tag: ""
serviceAccounts:
# Specifies whether service accounts should be created.
create: true
# Annotations to add to the service accounts.
annotations: {}
# Annotations to add only for the cartservice app. This allows to follow the least privilege principle where only cartservice needs to connect to external database for example via Workload Identity.
annotationsOnlyForCartservice: false
networkPolicies:
# Specifies if the NetworkPolicies are created or not. If true, one fine granular NetworkPolicy per app is created.
create: false
sidecars:
# Specifies if the Sidecars are created or not. If true, one fine granular Sidecar per app is created.
create: false
authorizationPolicies:
# Specifies if the AuthorizationPolicies are created or not. If true, one fine granular AuthorizationPolicy per app is created.
create: false
opentelemetryCollector:
create: false
name: opentelemetrycollector
# Specifies the project id for the otel collector. If set as "PROJECT_ID" (default value), an initContainer will automatically retrieve the project id value from the metadata server.
projectId: "PROJECT_ID"
googleCloudOperations:
profiler: false
tracing: false
metrics: false
seccompProfile:
enable: false
type: RuntimeDefault
securityContext:
enable: true
adService:
create: true
name: adservice
resources:
requests:
cpu: 200m
memory: 180Mi
limits:
cpu: 300m
memory: 300Mi
cartService:
create: true
name: cartservice
resources:
requests:
cpu: 200m
memory: 128Mi
limits:
cpu: 300m
memory: 256Mi
checkoutService:
create: true
name: checkoutservice
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
currencyService:
create: true
name: currencyservice
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
emailService:
create: true
name: emailservice
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
frontend:
create: true
name: frontend
externalService: true
cymbalBranding: false
# One of: local, gcp, aws, azure, onprem, alibaba. When not set, defaults to "local" unless running in GKE, otherwise auto-sets to gcp.
platform: local
singleSharedSession: false
virtualService:
create: false
hosts:
- "*"
gateway:
name: asm-ingressgateway
namespace: asm-ingress
labelKey: asm
labelValue: ingressgateway
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
loadGenerator:
create: true
name: loadgenerator
checkFrontendInitContainer: true
resources:
requests:
cpu: 300m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
paymentService:
create: true
name: paymentservice
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
productCatalogService:
create: true
name: productcatalogservice
# Specifies an extra latency to any request on productcatalogservice, by default no extra latency.
extraLatency: ""
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
recommendationService:
create: true
name: recommendationservice
resources:
requests:
cpu: 100m
memory: 220Mi
limits:
cpu: 200m
memory: 450Mi
shippingService:
create: true
name: shippingservice
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
cartDatabase:
# Specifies the type of the cartservice's database, could be either redis or spanner.
type: redis
connectionString: "redis-cart:6379"
inClusterRedis:
create: true
name: redis-cart
# Uses the public redis image from Docker Hub, otherwise will use the images.repository.
publicRepository: true
externalRedisTlsOrigination:
enable: false
name: exernal-redis-tls-origination
endpointAddress: ""
endpointPort: ""
certificate: ""
# @TODO: This service is not currently available in Helm.
# https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/kustomize/components/shopping-assistant
shoppingAssistantService:
create: false
name: shoppingassistantservice

View File

@@ -0,0 +1,46 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: allow-egress-googleapis
spec:
hosts:
- "accounts.google.com" # Used to get token
- "*.googleapis.com"
ports:
- number: 80
protocol: HTTP
name: http
- number: 443
protocol: HTTPS
name: https
---
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: allow-egress-google-metadata
spec:
hosts:
- metadata.google.internal
addresses:
- 169.254.169.254 # GCE metadata server
ports:
- number: 80
name: http
protocol: HTTP
- number: 443
name: https
protocol: HTTPS

View File

@@ -0,0 +1,44 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: frontend-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: frontend-ingress
spec:
hosts:
- "*"
gateways:
- frontend-gateway
http:
- route:
- destination:
host: frontend
port:
number: 80

View File

@@ -0,0 +1,27 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: frontend
spec:
hosts:
- "frontend.default.svc.cluster.local"
http:
- route:
- destination:
host: frontend
port:
number: 80

View File

@@ -0,0 +1,8 @@
# ./kubernetes-manifests
:warning: Kubernetes manifests provided in this directory are not directly
deployable to a cluster. They are meant to be used with `skaffold` command to
insert the correct `image:` tags.
Use the manifests in [/release](/release) directory which are configured with
pre-built public images.

View File

@@ -0,0 +1,88 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: adservice
labels:
app: adservice
spec:
selector:
matchLabels:
app: adservice
template:
metadata:
labels:
app: adservice
spec:
serviceAccountName: adservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: adservice
ports:
- containerPort: 9555
env:
- name: PORT
value: "9555"
resources:
requests:
cpu: 200m
memory: 180Mi
limits:
cpu: 300m
memory: 300Mi
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 15
grpc:
port: 9555
livenessProbe:
initialDelaySeconds: 20
periodSeconds: 15
grpc:
port: 9555
---
apiVersion: v1
kind: Service
metadata:
name: adservice
labels:
app: adservice
spec:
type: ClusterIP
selector:
app: adservice
ports:
- name: grpc
port: 9555
targetPort: 9555
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: adservice

View File

@@ -0,0 +1,156 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cartservice
labels:
app: cartservice
spec:
selector:
matchLabels:
app: cartservice
template:
metadata:
labels:
app: cartservice
spec:
serviceAccountName: cartservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: cartservice
ports:
- containerPort: 7070
env:
- name: REDIS_ADDR
value: "redis-cart:6379"
resources:
requests:
cpu: 200m
memory: 64Mi
limits:
cpu: 300m
memory: 128Mi
readinessProbe:
initialDelaySeconds: 15
grpc:
port: 7070
livenessProbe:
initialDelaySeconds: 15
periodSeconds: 10
grpc:
port: 7070
---
apiVersion: v1
kind: Service
metadata:
name: cartservice
labels:
app: cartservice
spec:
type: ClusterIP
selector:
app: cartservice
ports:
- name: grpc
port: 7070
targetPort: 7070
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: cartservice
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cart
labels:
app: redis-cart
spec:
selector:
matchLabels:
app: redis-cart
template:
metadata:
labels:
app: redis-cart
spec:
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: redis
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: redis:alpine
ports:
- containerPort: 6379
readinessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
livenessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
volumeMounts:
- mountPath: /data
name: redis-data
resources:
limits:
memory: 256Mi
cpu: 125m
requests:
cpu: 70m
memory: 200Mi
volumes:
- name: redis-data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: redis-cart
labels:
app: redis-cart
spec:
type: ClusterIP
selector:
app: redis-cart
ports:
- name: tcp-redis
port: 6379
targetPort: 6379

View File

@@ -0,0 +1,95 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkoutservice
labels:
app: checkoutservice
spec:
selector:
matchLabels:
app: checkoutservice
template:
metadata:
labels:
app: checkoutservice
spec:
serviceAccountName: checkoutservice
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: checkoutservice
ports:
- containerPort: 5050
readinessProbe:
grpc:
port: 5050
livenessProbe:
grpc:
port: 5050
env:
- name: PORT
value: "5050"
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "productcatalogservice:3550"
- name: SHIPPING_SERVICE_ADDR
value: "shippingservice:50051"
- name: PAYMENT_SERVICE_ADDR
value: "paymentservice:50051"
- name: EMAIL_SERVICE_ADDR
value: "emailservice:5000"
- name: CURRENCY_SERVICE_ADDR
value: "currencyservice:7000"
- name: CART_SERVICE_ADDR
value: "cartservice:7070"
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: checkoutservice
labels:
app: checkoutservice
spec:
type: ClusterIP
selector:
app: checkoutservice
ports:
- name: grpc
port: 5050
targetPort: 5050
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: checkoutservice

View File

@@ -0,0 +1,87 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: currencyservice
labels:
app: currencyservice
spec:
selector:
matchLabels:
app: currencyservice
template:
metadata:
labels:
app: currencyservice
spec:
serviceAccountName: currencyservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: currencyservice
ports:
- name: grpc
containerPort: 7000
env:
- name: PORT
value: "7000"
- name: DISABLE_PROFILER
value: "1"
readinessProbe:
grpc:
port: 7000
livenessProbe:
grpc:
port: 7000
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: currencyservice
labels:
app: currencyservice
spec:
type: ClusterIP
selector:
app: currencyservice
ports:
- name: grpc
port: 7000
targetPort: 7000
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: currencyservice

View File

@@ -0,0 +1,88 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: emailservice
labels:
app: emailservice
spec:
selector:
matchLabels:
app: emailservice
template:
metadata:
labels:
app: emailservice
spec:
serviceAccountName: emailservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: emailservice
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
- name: DISABLE_PROFILER
value: "1"
readinessProbe:
periodSeconds: 5
grpc:
port: 8080
livenessProbe:
periodSeconds: 5
grpc:
port: 8080
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: emailservice
labels:
app: emailservice
spec:
type: ClusterIP
selector:
app: emailservice
ports:
- name: grpc
port: 5000
targetPort: 8080
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: emailservice

View File

@@ -0,0 +1,141 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: frontend
spec:
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
annotations:
sidecar.istio.io/rewriteAppHTTPProbers: "true"
spec:
serviceAccountName: frontend
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: frontend
ports:
- containerPort: 8080
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8080
httpHeaders:
- name: "Cookie"
value: "shop_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8080
httpHeaders:
- name: "Cookie"
value: "shop_session-id=x-liveness-probe"
env:
- name: PORT
value: "8080"
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "productcatalogservice:3550"
- name: CURRENCY_SERVICE_ADDR
value: "currencyservice:7000"
- name: CART_SERVICE_ADDR
value: "cartservice:7070"
- name: RECOMMENDATION_SERVICE_ADDR
value: "recommendationservice:8080"
- name: SHIPPING_SERVICE_ADDR
value: "shippingservice:50051"
- name: CHECKOUT_SERVICE_ADDR
value: "checkoutservice:5050"
- name: AD_SERVICE_ADDR
value: "adservice:9555"
- name: SHOPPING_ASSISTANT_SERVICE_ADDR
value: "shoppingassistantservice:80"
# # ENV_PLATFORM: One of: local, gcp, aws, azure, onprem, alibaba
# # When not set, defaults to "local" unless running in GKE, otherwies auto-sets to gcp
# - name: ENV_PLATFORM
# value: "aws"
- name: ENABLE_PROFILER
value: "0"
# - name: CYMBAL_BRANDING
# value: "true"
# - name: ENABLE_ASSISTANT
# value: "true"
# - name: FRONTEND_MESSAGE
# value: "Replace this with a message you want to display on all pages."
# As part of an optional Google Cloud demo, you can run an optional microservice called the "packaging service".
# - name: PACKAGING_SERVICE_URL
# value: "" # This value would look like "http://123.123.123"
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: frontend
labels:
app: frontend
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
port: 80
targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: frontend-external
labels:
app: frontend
spec:
type: LoadBalancer
selector:
app: frontend
ports:
- name: http
port: 80
targetPort: 8080
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: frontend

View File

@@ -0,0 +1,39 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- adservice.yaml
- cartservice.yaml
- checkoutservice.yaml
- currencyservice.yaml
- emailservice.yaml
- frontend.yaml
# - loadgenerator.yaml # During development, the loadgenerator module inside skaffold.yaml will be used.
- paymentservice.yaml
- productcatalogservice.yaml
- recommendationservice.yaml
- shippingservice.yaml
# components:
# - ../kustomize/components/cymbal-branding
# - ../kustomize/components/google-cloud-operations
# - ../kustomize/components/memorystore
# - ../kustomize/components/network-policies
# - ../kustomize/components/alloydb
# - ../kustomize/components/shopping-assistant
# - ../kustomize/components/spanner
# - ../kustomize/components/container-images-tag
# - ../kustomize/components/container-images-tag-suffix
# - ../kustomize/components/container-images-registry

View File

@@ -0,0 +1,99 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: loadgenerator
labels:
app: loadgenerator
spec:
selector:
matchLabels:
app: loadgenerator
replicas: 1
template:
metadata:
labels:
app: loadgenerator
annotations:
sidecar.istio.io/rewriteAppHTTPProbers: "true"
spec:
serviceAccountName: loadgenerator
terminationGracePeriodSeconds: 5
restartPolicy: Always
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
initContainers:
- command:
- /bin/sh
- -exc
- |
MAX_RETRIES=12
RETRY_INTERVAL=10
for i in $(seq 1 $MAX_RETRIES); do
echo "Attempt $i: Pinging frontend: ${FRONTEND_ADDR}..."
STATUSCODE=$(wget --server-response http://${FRONTEND_ADDR} 2>&1 | awk '/^ HTTP/{print $2}')
if [ $STATUSCODE -eq 200 ]; then
echo "Frontend is reachable."
exit 0
fi
echo "Error: Could not reach frontend - Status code: ${STATUSCODE}"
sleep $RETRY_INTERVAL
done
echo "Failed to reach frontend after $MAX_RETRIES attempts."
exit 1
name: frontend-check
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: busybox:latest
env:
- name: FRONTEND_ADDR
value: "frontend:80"
containers:
- name: main
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: loadgenerator
env:
- name: FRONTEND_ADDR
value: "frontend:80"
- name: USERS
value: "10"
- name: RATE
value: "1"
resources:
requests:
cpu: 300m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: loadgenerator

View File

@@ -0,0 +1,86 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: paymentservice
labels:
app: paymentservice
spec:
selector:
matchLabels:
app: paymentservice
template:
metadata:
labels:
app: paymentservice
spec:
serviceAccountName: paymentservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: paymentservice
ports:
- containerPort: 50051
env:
- name: PORT
value: "50051"
- name: DISABLE_PROFILER
value: "1"
readinessProbe:
grpc:
port: 50051
livenessProbe:
grpc:
port: 50051
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: paymentservice
labels:
app: paymentservice
spec:
type: ClusterIP
selector:
app: paymentservice
ports:
- name: grpc
port: 50051
targetPort: 50051
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: paymentservice

View File

@@ -0,0 +1,86 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: productcatalogservice
labels:
app: productcatalogservice
spec:
selector:
matchLabels:
app: productcatalogservice
template:
metadata:
labels:
app: productcatalogservice
spec:
serviceAccountName: productcatalogservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: productcatalogservice
ports:
- containerPort: 3550
env:
- name: PORT
value: "3550"
- name: DISABLE_PROFILER
value: "1"
readinessProbe:
grpc:
port: 3550
livenessProbe:
grpc:
port: 3550
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: productcatalogservice
labels:
app: productcatalogservice
spec:
type: ClusterIP
selector:
app: productcatalogservice
ports:
- name: grpc
port: 3550
targetPort: 3550
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: productcatalogservice

View File

@@ -0,0 +1,90 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: recommendationservice
labels:
app: recommendationservice
spec:
selector:
matchLabels:
app: recommendationservice
template:
metadata:
labels:
app: recommendationservice
spec:
serviceAccountName: recommendationservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: recommendationservice
ports:
- containerPort: 8080
readinessProbe:
periodSeconds: 5
grpc:
port: 8080
livenessProbe:
periodSeconds: 5
grpc:
port: 8080
env:
- name: PORT
value: "8080"
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "productcatalogservice:3550"
- name: DISABLE_PROFILER
value: "1"
resources:
requests:
cpu: 100m
memory: 220Mi
limits:
cpu: 200m
memory: 450Mi
---
apiVersion: v1
kind: Service
metadata:
name: recommendationservice
labels:
app: recommendationservice
spec:
type: ClusterIP
selector:
app: recommendationservice
ports:
- name: grpc
port: 8080
targetPort: 8080
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: recommendationservice

View File

@@ -0,0 +1,86 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: shippingservice
labels:
app: shippingservice
spec:
selector:
matchLabels:
app: shippingservice
template:
metadata:
labels:
app: shippingservice
spec:
serviceAccountName: shippingservice
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: shippingservice
ports:
- containerPort: 50051
env:
- name: PORT
value: "50051"
- name: DISABLE_PROFILER
value: "1"
readinessProbe:
periodSeconds: 5
grpc:
port: 50051
livenessProbe:
grpc:
port: 50051
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: shippingservice
labels:
app: shippingservice
spec:
type: ClusterIP
selector:
app: shippingservice
ports:
- name: grpc
port: 50051
targetPort: 50051
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: shippingservice

140
kustomize/README.md Normal file
View File

@@ -0,0 +1,140 @@
# Use Online Boutique with Kustomize
This page contains instructions on deploying variations of the [Online Boutique](https://github.com/GoogleCloudPlatform/microservices-demo) sample application using [Kustomize](https://kustomize.io/). Each variations is designed as a [**Kustomize component**](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/components.md), so multiple variations can be composed together in the deployment.
## What is Kustomize?
Kustomize is a Kubernetes configuration management tool that allows users to customize their manifest configurations without duplication. Its commands are built into `kubectl` as `apply -k`. More information on Kustomize can be found on the [official Kustomize website](https://kustomize.io/).
## Prerequisites
Optionally, [install the `kustomize` binary](https://kubectl.docs.kubernetes.io/installation/) to avoid manually editing a `kustomization.yaml` file. Online Boutique's instructions will often use `kustomize edit` (like `kustomize edit add component components/some-component`), but you can skip these commands and instead add components manually to the [`/kustomize/kustomization.yaml` file](/kustomize/kustomization.yaml).
You need to have a Kubernetes cluster where you will deploy the Online Boutique's Kubernetes manifests. To set up a GKE (Google Kubernetes Engine) cluster, you can follow the instruction in the [root `/README.md`](/).
## Deploy Online Boutique with Kustomize
1. From the root folder of this repository, navigate to the `kustomize/` directory.
```bash
cd kustomize/
```
1. See what the default Kustomize configuration defined by `kustomize/kustomization.yaml` will generate (without actually deploying them yet).
```bash
kubectl kustomize .
```
1. Apply the default Kustomize configuration (`kustomize/kustomization.yaml`).
```bash
kubectl apply -k .
```
1. Wait for all Pods to show `STATUS` of `Running`.
```bash
kubectl get pods
```
The output should be similar to the following:
```terminal
NAME READY STATUS RESTARTS AGE
adservice-76bdd69666-ckc5j 1/1 Running 0 2m58s
cartservice-66d497c6b7-dp5jr 1/1 Running 0 2m59s
checkoutservice-666c784bd6-4jd22 1/1 Running 0 3m1s
currencyservice-5d5d496984-4jmd7 1/1 Running 0 2m59s
emailservice-667457d9d6-75jcq 1/1 Running 0 3m2s
frontend-6b8d69b9fb-wjqdg 1/1 Running 0 3m1s
loadgenerator-665b5cd444-gwqdq 1/1 Running 0 3m
paymentservice-68596d6dd6-bf6bv 1/1 Running 0 3m
productcatalogservice-557d474574-888kr 1/1 Running 0 3m
recommendationservice-69c56b74d4-7z8r5 1/1 Running 0 3m1s
shippingservice-6ccc89f8fd-v686r 1/1 Running 0 2m58s
```
_Note: It may take 2-3 minutes before the changes are reflected on the deployment._
1. Access the web frontend in a browser using the frontend's `EXTERNAL_IP`.
```bash
kubectl get service frontend-external | awk '{print $4}'
```
Note: you may see `<pending>` while GCP provisions the load balancer. If this happens, wait a few minutes and re-run the command.
## Deploy Online Boutique variations with Kustomize
Here is the list of the variations available as Kustomize components that you could leverage:
- [**Change to the Cymbal Shops Branding**](components/cymbal-branding)
- Changes all Online Boutique-related branding to Google Cloud's fictitious company — Cymbal Shops. The code adds/enables an environment variable `CYMBAL_BRANDING` in the `frontend` service.
- [**Integrate with Google Cloud Operations**](components/google-cloud-operations)
- Enables Monitoring (Stats), Tracing, and Profiler for various services within Online Boutique. The code adds the appropriare environment variables (`ENABLE_STATS`, `ENABLE_TRACING`, `DISABLE_PROFILER`) for each YAML config file.
- [**Integrate with Memorystore (Redis)**](components/memorystore)
- The default Online Boutique deployment uses the in-cluster `redis` database for storing the contents of its shopping cart. The Memorystore deployment variation overrides the default database with its own Memorystore (Redis) database. These changes directly affect `cartservice`.
- [**Integrate with Spanner**](components/spanner)
- The default Online Boutique deployment uses the in-cluster `redis` database for storing the contents of its shopping cart. The Spanner deployment variation overrides the default database with its own Spanner database. These changes directly affect `cartservice`.
- [**Integrate with AlloyDB**](components/alloydb)
- The default Online Boutique deployment uses the in-cluster `redis` database for storing the contents of its shopping cart. The AlloyDB deployment variation overrides the default database with its own AlloyDB database.
These changes directly affect `cartservice`.
- [**Secure with Network Policies**](components/network-policies)
- Deploy fine granular `NetworkPolicies` for Online Boutique.
- [**Update the registry name of the container images**](components/container-images-registry)
- [**Update the image tag of the container images**](components/container-images-tag)
- [**Add an image tag suffix to the container images**](components/container-images-tag-suffix)
- [**Do not expose the `frontend` publicly**](components/non-public-frontend)
- [**Set the `frontend` to manage only one single shared session**](components/single-shared-session)
- [**Configure `Istio` service mesh resources**](components/service-mesh-istio)
### Select variations
To customize Online Boutique with its variations, you need to update the default `kustomize/kustomization.yaml` file. You could do that manually, use `sed`, or use the `kustomize edit` command like illustrated below.
#### Use `kustomize edit` to select variations
Here is an example with the [**Cymbal Shops Branding**](components/cymbal-branding) variation, from the `kustomize/` folder, run the command below:
```bash
kustomize edit add component components/cymbal-branding
```
You could now combine it with other variations, like for example with the [**Google Cloud Operations**](components/google-cloud-operations) variation:
```bash
kustomize edit add component components/google-cloud-operations
```
### Deploy selected variations
Like explained earlier, you can locally render these manifests by running `kubectl kustomize .` as well as deploying them by running `kubectl apply -k .`.
So for example, the associated `kustomization.yaml` could look like:
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- base
components:
- components/cymbal-branding
- components/google-cloud-operations
```
### Use remote Kustomize targets
Kustomize allows you to reference public remote resources so the `kustomization.yaml` could look like:
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- github.com/GoogleCloudPlatform/microservices-demo/kustomize/base
components:
- github.com/GoogleCloudPlatform/microservices-demo/kustomize/components/cymbal-branding
- github.com/GoogleCloudPlatform/microservices-demo/kustomize/components/google-cloud-operations
```
Learn more about [Kustomize remote targets](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/remoteBuild.md).

View File

@@ -0,0 +1,88 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: adservice
labels:
app: adservice
spec:
selector:
matchLabels:
app: adservice
template:
metadata:
labels:
app: adservice
spec:
serviceAccountName: adservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: us-central1-docker.pkg.dev/google-samples/microservices-demo/adservice:v0.10.4
ports:
- containerPort: 9555
env:
- name: PORT
value: "9555"
resources:
requests:
cpu: 200m
memory: 180Mi
limits:
cpu: 300m
memory: 300Mi
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 15
grpc:
port: 9555
livenessProbe:
initialDelaySeconds: 20
periodSeconds: 15
grpc:
port: 9555
---
apiVersion: v1
kind: Service
metadata:
name: adservice
labels:
app: adservice
spec:
type: ClusterIP
selector:
app: adservice
ports:
- name: grpc
port: 9555
targetPort: 9555
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: adservice

View File

@@ -0,0 +1,156 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cartservice
labels:
app: cartservice
spec:
selector:
matchLabels:
app: cartservice
template:
metadata:
labels:
app: cartservice
spec:
serviceAccountName: cartservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: us-central1-docker.pkg.dev/google-samples/microservices-demo/cartservice:v0.10.4
ports:
- containerPort: 7070
env:
- name: REDIS_ADDR
value: "redis-cart:6379"
resources:
requests:
cpu: 200m
memory: 64Mi
limits:
cpu: 300m
memory: 128Mi
readinessProbe:
initialDelaySeconds: 15
grpc:
port: 7070
livenessProbe:
initialDelaySeconds: 15
periodSeconds: 10
grpc:
port: 7070
---
apiVersion: v1
kind: Service
metadata:
name: cartservice
labels:
app: cartservice
spec:
type: ClusterIP
selector:
app: cartservice
ports:
- name: grpc
port: 7070
targetPort: 7070
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: cartservice
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cart
labels:
app: redis-cart
spec:
selector:
matchLabels:
app: redis-cart
template:
metadata:
labels:
app: redis-cart
spec:
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: redis
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: redis:alpine
ports:
- containerPort: 6379
readinessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
livenessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
volumeMounts:
- mountPath: /data
name: redis-data
resources:
limits:
memory: 256Mi
cpu: 125m
requests:
cpu: 70m
memory: 200Mi
volumes:
- name: redis-data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: redis-cart
labels:
app: redis-cart
spec:
type: ClusterIP
selector:
app: redis-cart
ports:
- name: tcp-redis
port: 6379
targetPort: 6379

View File

@@ -0,0 +1,95 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkoutservice
labels:
app: checkoutservice
spec:
selector:
matchLabels:
app: checkoutservice
template:
metadata:
labels:
app: checkoutservice
spec:
serviceAccountName: checkoutservice
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: us-central1-docker.pkg.dev/google-samples/microservices-demo/checkoutservice:v0.10.4
ports:
- containerPort: 5050
readinessProbe:
grpc:
port: 5050
livenessProbe:
grpc:
port: 5050
env:
- name: PORT
value: "5050"
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "productcatalogservice:3550"
- name: SHIPPING_SERVICE_ADDR
value: "shippingservice:50051"
- name: PAYMENT_SERVICE_ADDR
value: "paymentservice:50051"
- name: EMAIL_SERVICE_ADDR
value: "emailservice:5000"
- name: CURRENCY_SERVICE_ADDR
value: "currencyservice:7000"
- name: CART_SERVICE_ADDR
value: "cartservice:7070"
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: checkoutservice
labels:
app: checkoutservice
spec:
type: ClusterIP
selector:
app: checkoutservice
ports:
- name: grpc
port: 5050
targetPort: 5050
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: checkoutservice

View File

@@ -0,0 +1,87 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: currencyservice
labels:
app: currencyservice
spec:
selector:
matchLabels:
app: currencyservice
template:
metadata:
labels:
app: currencyservice
spec:
serviceAccountName: currencyservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: us-central1-docker.pkg.dev/google-samples/microservices-demo/currencyservice:v0.10.4
ports:
- name: grpc
containerPort: 7000
env:
- name: PORT
value: "7000"
- name: DISABLE_PROFILER
value: "1"
readinessProbe:
grpc:
port: 7000
livenessProbe:
grpc:
port: 7000
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: currencyservice
labels:
app: currencyservice
spec:
type: ClusterIP
selector:
app: currencyservice
ports:
- name: grpc
port: 7000
targetPort: 7000
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: currencyservice

View File

@@ -0,0 +1,88 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: emailservice
labels:
app: emailservice
spec:
selector:
matchLabels:
app: emailservice
template:
metadata:
labels:
app: emailservice
spec:
serviceAccountName: emailservice
terminationGracePeriodSeconds: 5
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: us-central1-docker.pkg.dev/google-samples/microservices-demo/emailservice:v0.10.4
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
- name: DISABLE_PROFILER
value: "1"
readinessProbe:
periodSeconds: 5
grpc:
port: 8080
livenessProbe:
periodSeconds: 5
grpc:
port: 8080
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: emailservice
labels:
app: emailservice
spec:
type: ClusterIP
selector:
app: emailservice
ports:
- name: grpc
port: 5000
targetPort: 8080
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: emailservice

View File

@@ -0,0 +1,141 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: frontend
spec:
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
annotations:
sidecar.istio.io/rewriteAppHTTPProbers: "true"
spec:
serviceAccountName: frontend
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: us-central1-docker.pkg.dev/google-samples/microservices-demo/frontend:v0.10.4
ports:
- containerPort: 8080
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8080
httpHeaders:
- name: "Cookie"
value: "shop_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8080
httpHeaders:
- name: "Cookie"
value: "shop_session-id=x-liveness-probe"
env:
- name: PORT
value: "8080"
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "productcatalogservice:3550"
- name: CURRENCY_SERVICE_ADDR
value: "currencyservice:7000"
- name: CART_SERVICE_ADDR
value: "cartservice:7070"
- name: RECOMMENDATION_SERVICE_ADDR
value: "recommendationservice:8080"
- name: SHIPPING_SERVICE_ADDR
value: "shippingservice:50051"
- name: CHECKOUT_SERVICE_ADDR
value: "checkoutservice:5050"
- name: AD_SERVICE_ADDR
value: "adservice:9555"
- name: SHOPPING_ASSISTANT_SERVICE_ADDR
value: "shoppingassistantservice:80"
# # ENV_PLATFORM: One of: local, gcp, aws, azure, onprem, alibaba
# # When not set, defaults to "local" unless running in GKE, otherwies auto-sets to gcp
# - name: ENV_PLATFORM
# value: "aws"
- name: ENABLE_PROFILER
value: "0"
# - name: CYMBAL_BRANDING
# value: "true"
# - name: ENABLE_ASSISTANT
# value: "true"
# - name: FRONTEND_MESSAGE
# value: "Replace this with a message you want to display on all pages."
# As part of an optional Google Cloud demo, you can run an optional microservice called the "packaging service".
# - name: PACKAGING_SERVICE_URL
# value: "" # This value would look like "http://123.123.123"
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: frontend
labels:
app: frontend
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
port: 80
targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: frontend-external
labels:
app: frontend
spec:
type: LoadBalancer
selector:
app: frontend
ports:
- name: http
port: 80
targetPort: 8080
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: frontend

Some files were not shown because too many files have changed in this diff Show More