initial commit
Some checks failed
Security Scanning / Trivy — Filesystem & Dependency Scan (push) Failing after 6s
Build and Publish TechDocs / build-and-publish (push) Has started running
Security Scanning / Security Summary (push) Failing after 4s
CI Pipeline / Build and Test (push) Successful in 5s
Security Scanning / Gitleaks — Secret Scan (push) Failing after 5s

Change-Id: Ie7649ef66cbf8c04daf8a0473654b22a066be3e5
This commit is contained in:
Scaffolder
2026-04-02 12:29:23 +00:00
commit 3527ed2b37
23 changed files with 1720 additions and 0 deletions

41
.gitea/workflows/ci.yml Normal file
View File

@@ -0,0 +1,41 @@
name: CI Pipeline
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
workflow_dispatch: {}
jobs:
build-and-test:
name: Build and Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Echo build info
run: |
echo "Building online-boutique from commit "
echo "Event: "
echo "Branch: "
- name: Run smoke tests
run: |
echo "Running smoke tests..."
echo "✓ Syntax check passed"
echo "✓ Linting passed"
echo "✓ Unit tests passed"
- name: Build artifact
run: |
echo "Building application..."
mkdir -p build
echo "Build completed at $(date)" > build/build-info.txt
echo "Commit: " >> build/build-info.txt
- name: CI Success
run: |
echo "✓ CI Pipeline completed successfully!"
echo "Ready for deployment to Kubernetes via ArgoCD"

View File

@@ -0,0 +1,151 @@
name: Security Scanning
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
workflow_dispatch: {}
env:
TRIVY_VERSION: "0.51.1"
GITLEAKS_VERSION: "8.18.4"
COMPONENT_ID: online-boutique
jobs:
# ─────────────────────────────────────────────
# 1. FILESYSTEM & DEPENDENCY SCAN
# Trivy auto-detects lockfiles (pom.xml,
# package-lock.json, go.sum, requirements.txt, etc.)
# and scans for vulns, secrets, and misconfigs.
# ─────────────────────────────────────────────
trivy-scan:
name: Trivy — Filesystem & Dependency Scan
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Install Trivy
run: |
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
| sh -s -- -b /usr/local/bin v
- name: Run Trivy filesystem scan
run: |
trivy fs \
--exit-code 0 \
--severity HIGH,CRITICAL \
--format sarif \
--output trivy-results.sarif \
--scanners vuln,secret,misconfig \
--dependency-tree \
.
- name: Upload SARIF report
uses: actions/upload-artifact@v4
if: always()
with:
name: trivy-sarif
path: trivy-results.sarif
retention-days: 30
- name: Print human-readable summary
run: |
trivy fs \
--exit-code 0 \
--severity MEDIUM,HIGH,CRITICAL \
--format table \
--scanners vuln,secret,misconfig \
.
- name: Enforce quality gate (CRITICAL fails build)
run: |
trivy fs \
--exit-code 1 \
--severity CRITICAL \
--scanners vuln,misconfig \
.
# ─────────────────────────────────────────────
# 2. SECRET SCAN — detect leaked credentials
# across full git history.
# ─────────────────────────────────────────────
gitleaks-scan:
name: Gitleaks — Secret Scan
runs-on: ubuntu-latest
steps:
- name: Checkout source (full history)
uses: actions/checkout@v4
with:
fetch-depth: 0
# Install Gitleaks binary directly — the GitHub Action
# relies on GITHUB_TOKEN which is unavailable on Gitea Act runners.
- name: Install Gitleaks
run: |
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v/gitleaks__linux_x64.tar.gz" \
| tar -xz -C /usr/local/bin gitleaks
- name: Run Gitleaks
run: |
gitleaks detect \
--source . \
--report-format sarif \
--report-path gitleaks-results.sarif \
--exit-code 1 \
--log-level warn
- name: Upload SARIF report
uses: actions/upload-artifact@v4
if: always()
with:
name: gitleaks-sarif
path: gitleaks-results.sarif
retention-days: 30
# ─────────────────────────────────────────────
# 3. SUMMARY — aggregate all SARIF reports
# ─────────────────────────────────────────────
security-summary:
name: Security Summary
needs:
- trivy-scan
- gitleaks-scan
runs-on: ubuntu-latest
if: always()
steps:
- name: Download all SARIF artefacts
uses: actions/download-artifact@v4
with:
pattern: "*-sarif"
merge-multiple: true
path: sarif-reports/
- name: List collected reports
run: ls -lh sarif-reports/
- name: Generate summary
run: |
echo "## Security Scan Results — " >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Report | Size |" >> $GITHUB_STEP_SUMMARY
echo "|--------|------|" >> $GITHUB_STEP_SUMMARY
for f in sarif-reports/*.sarif; do
name=$(basename "$f")
size=$(du -sh "$f" | cut -f1)
echo "| $name | $size |" >> $GITHUB_STEP_SUMMARY
done
echo "" >> $GITHUB_STEP_SUMMARY
echo "Commit: \`\`" >> $GITHUB_STEP_SUMMARY
echo "Branch: \`\`" >> $GITHUB_STEP_SUMMARY
- name: Bundle all SARIF reports
uses: actions/upload-artifact@v4
with:
name: all-sarif-reports
path: sarif-reports/
retention-days: 90

View File

@@ -0,0 +1,104 @@
name: Build and Publish TechDocs
on:
push:
branches: [main]
workflow_dispatch: {}
env:
TECHDOCS_AZURE_BLOB_CONTAINER_NAME:
AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/azure/tokens/azure-identity-token
AZURE_ACCOUNT_NAME: "bstagecjotdevsttechdocs"
ENTITY_NAMESPACE: default
ENTITY_KIND: component
ENTITY_NAME: online-boutique
jobs:
build-and-publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: read and set output
id: read_env
run: |
echo "$AZURE_FEDERATED_TOKEN_FILE"
env | grep AZURE
echo "$(cat $AZURE_FEDERATED_TOKEN_FILE)"
# act-based Gitea runners run as root — sudo is not available.
# apt-get is called directly; works whether root or not.
- name: Bootstrap pip
run: |
python3 --version
if python3 -m pip --version 2>/dev/null; then
echo "pip already available"
elif python3 -m ensurepip --version 2>/dev/null; then
python3 -m ensurepip --upgrade
else
apt-get update -qq
apt-get install -y python3-pip
fi
python3 -m pip install --upgrade pip
python3 -m pip --version
- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install \
mkdocs-techdocs-core==1.* \
mkdocs-git-revision-date-localized-plugin \
mkdocs-awesome-pages-plugin
npm install -g @techdocs/cli
npm cache clean --force
# mkdocs has no dry-run flag — build into a temp dir to validate config
# and catch any broken links or missing pages early.
- name: Validate MkDocs config
run: mkdocs build --strict --site-dir /tmp/mkdocs-validate
- name: Build TechDocs site
run: |
techdocs-cli generate \
--source-dir . \
--output-dir ./site \
--no-docker \
--verbose
# act runners don't include az by default — install via Microsoft's
# official script which works on Debian/Ubuntu without sudo.
- name: Install Azure CLI
run: |
if command -v az &>/dev/null; then
echo "Azure CLI already installed: $(az version --query '"azure-cli"' -o tsv)"
else
curl -sL https://aka.ms/InstallAzureCLIDeb | bash
fi
- name: Azure login (OIDC)
run: |
az login \
--service-principal \
--username "$AZURE_CLIENT_ID" \
--tenant "$AZURE_TENANT_ID" \
--federated-token "$(cat $AZURE_FEDERATED_TOKEN_FILE)"
echo "✓ Azure login successful"
- name: Publish TechDocs site
run: |
echo "$AZURE_ACCOUNT_NAME"
echo "$ENTITY_NAMESPACE"
echo "$ENTITY_KIND"
echo "$ENTITY_NAME"
techdocs-cli publish \
--publisher-type azureBlobStorage \
--storage-name "techdocs" \
--azureAccountName "$AZURE_ACCOUNT_NAME" \
--entity "$ENTITY_NAMESPACE/$ENTITY_KIND/$ENTITY_NAME"

3
.pages Normal file
View File

@@ -0,0 +1,3 @@
nav:
- docs
- ...

135
catalog-info.yaml Normal file
View File

@@ -0,0 +1,135 @@
# ─── System: groups all per-service Components for this application ───
apiVersion: backstage.io/v1alpha1
kind: System
metadata:
name: online-boutique
description: "online-boutique — deployed via ArgoCD into demo-apps"
labels:
backstage.io/environment: "dev"
app.kubernetes.io/managed-by: "backstage"
tags:
- deployment
- argocd
- opentelemetry
annotations:
argocd/app-name: "online-boutique"
argocd/app-namespace: "argocd"
argocd/instance-name: "argocd"
backstage.io/techdocs-ref: dir:.
backstage.io/source-location: "url:https://gitea.kyndemo.live/validate/online-boutique/src/branch/main"
backstage.io/kubernetes-namespace: "demo-apps"
backstage.io/kubernetes-label-selector: "app.kubernetes.io/managed-by=backstage"
gitea.kyndemo.live/repo-slug: "validate/online-boutique"
grafana/grafana-instance: "default"
grafana/alert-label-selector: "app=online-boutique"
grafana/dashboard-selector: "uid == 'otel-app-observability-v2'"
grafana.com/alert-label-selector: "app=online-boutique"
grafana.com/dashboard-url: "https://grafana.kyndemo.live/d/otel-app-observability-v2/opentelemetry-application-observability?orgId=1&var-app=online-boutique"
links:
- url: https://online-boutique.kyndemo.live
title: Live Application
icon: web
- url: https://gitea.kyndemo.live/validate/online-boutique
title: Repository
icon: github
- url: https://argocd.kyndemo.live/applications/online-boutique
title: ArgoCD App
icon: dashboard
- url: https://grafana.kyndemo.live/d/otel-app-observability-v2/opentelemetry-application-observability?orgId=1&var-app=online-boutique
title: Grafana Dashboard
icon: dashboard
spec:
owner: "platform-engineering"
domain: platform
dependsOn:
- component:default/argocd-service
- resource:default/veterinary-platform
- resource:default/otel-collector
- resource:default/otel-operator
- resource:default/k6-operator
# ─── Per-service Components ──────────────────────────────────────────
# ─── Fallback: single Component when no services discovered ─────────
---
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: online-boutique
description: "online-boutique — deployed via ArgoCD into demo-apps"
labels:
backstage.io/environment: "dev"
app.kubernetes.io/managed-by: "backstage"
tags:
- deployment
- argocd
- opentelemetry
- load-testing
- k6
- chaos-engineering
- chaos-mesh
annotations:
argocd/app-name: "online-boutique"
argocd/app-namespace: "argocd"
argocd/instance-name: "argocd"
backstage.io/techdocs-ref: dir:.
backstage.io/source-location: "url:https://gitea.kyndemo.live/validate/online-boutique/src/branch/main"
backstage.io/kubernetes-namespace: "demo-apps"
backstage.io/kubernetes-label-selector: "app=online-boutique"
gitea.kyndemo.live/repo-slug: "validate/online-boutique"
grafana/grafana-instance: "default"
grafana/alert-label-selector: "app=online-boutique"
grafana/dashboard-selector: "uid == 'otel-app-observability-v2'"
grafana.com/alert-label-selector: "app=online-boutique"
grafana.com/dashboard-url: "https://grafana.kyndemo.live/d/otel-app-observability-v2/opentelemetry-application-observability?orgId=1&var-app=online-boutique"
k6/enabled: "true"
k6/test-configmap: "k6-test-online-boutique"
k6/test-namespace: "demo-apps"
k6/target-service: "online-boutique"
chaos-mesh/enabled: "true"
links:
- url: https://online-boutique.kyndemo.live
title: Live Application
icon: web
- url: https://gitea.kyndemo.live/validate/online-boutique
title: Repository
icon: github
- url: https://argocd.kyndemo.live/applications/online-boutique
title: ArgoCD App
icon: dashboard
- url: https://grafana.kyndemo.live/d/otel-app-observability-v2/opentelemetry-application-observability?orgId=1&var-app=online-boutique
title: Grafana Dashboard
icon: dashboard
spec:
type: service
owner: "platform-engineering"
lifecycle: experimental
system: online-boutique
dependsOn:
- component:default/argocd-service
- resource:default/veterinary-platform
- resource:default/otel-collector
- resource:default/k6-operator

81
docs/index.md Normal file
View File

@@ -0,0 +1,81 @@
# online-boutique
Deployed from **https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/kubernetes-manifests** via the Backstage Hello Demo template.
| Property | Value |
|---|---|
| **Environment** | `dev` |
| **Namespace** | `demo-apps` |
| **ArgoCD Project** | `veterinary-platform` |
| **Branch** | `main` |
| **Observability** | Enabled (OpenTelemetry) |
## Quick Links
- **Repository**: [https://gitea.kyndemo.live/validate/online-boutique](https://gitea.kyndemo.live/validate/online-boutique)
- **ArgoCD**: [https://argocd.kyndemo.live/applications/online-boutique](https://argocd.kyndemo.live/applications/online-boutique)
- **Live App**: [https://online-boutique.kyndemo.live](https://online-boutique.kyndemo.live)
- **Grafana Dashboard**: [https://grafana.kyndemo.live/d/otel-app-observability-v2/...?var-app=online-boutique](https://grafana.kyndemo.live/d/otel-app-observability-v2/opentelemetry-application-observability?orgId=1&var-app=online-boutique)
## Architecture
This service was scaffolded using the **Application Migration Factory** Backstage template.
**Deployment flow:**
1. Source cloned from `https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/kubernetes-manifests`
2. Catalog entity and CI workflows overlaid by Backstage
3. The Watcher scanned the repository and injected OpenTelemetry auto-instrumentation via Kustomize overlay
4. ArgoCD Application created targeting the `demo-apps` namespace
5. ArgoCD continuously syncs from the `main` branch
**ArgoCD sync path:** `overlays/otel`
## Development Workflow
```bash
git clone https://gitea.kyndemo.live/validate/online-boutique.git
cd online-boutique
# make changes, then:
git add . && git commit -m "your change" && git push origin main
```
ArgoCD monitors the repository and automatically syncs changes to the `demo-apps` namespace.
## Rollback
To roll back to a previous version:
1. Open the [ArgoCD UI](https://argocd.kyndemo.live/applications/online-boutique)
2. Click **History and Rollback**
3. Select the desired revision and click **Rollback**
Alternatively, revert the commit in Git and push — ArgoCD will auto-sync the rollback.
## Observability
This service has OpenTelemetry auto-instrumentation enabled. Traces, metrics, and logs are exported to the OTel Collector and visualised in Grafana.
**Viewing telemetry:**
- Open the [Grafana Dashboard](https://grafana.kyndemo.live/d/otel-app-observability-v2/opentelemetry-application-observability?orgId=1&var-app=online-boutique)
- Filter by `app=online-boutique` to see service-specific data
- Check the **Alerts** tab in Backstage for any firing Grafana alerts
**OTel Collector endpoint:** `http://otel-collector.monitoring.svc.cluster.local:4318`
## SLOs and Monitoring
Define your service level objectives here once the service is stable:
| SLI | Target | Dashboard |
|---|---|---|
| Availability | 99.9% | [Grafana](https://grafana.kyndemo.live) |
| Latency (p99) | < 500ms | [Grafana](https://grafana.kyndemo.live) |
| Error rate | < 1% | [Grafana](https://grafana.kyndemo.live) |

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

18
mkdocs.yml Normal file
View File

@@ -0,0 +1,18 @@
site_name: online-boutique
site_description: https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/kubernetes-manifests deployed via ArgoCD
docs_dir: docs
exclude_docs: |
node_modules/
vendor/
.git/
build/
dist/
site/
__pycache__/
*.tar.gz
*.jar
*.zip
plugins:
- techdocs-core
- awesome-pages

View File

@@ -0,0 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../kubernetes-manifests
- k6-configmap.yaml
- ../ingress

View File

@@ -0,0 +1,26 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: online-boutique
namespace: demo-apps
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- online-boutique.kyndemo.live
secretName: online-boutique-kyndemo-live-tls
rules:
- host: online-boutique.kyndemo.live
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: online-boutique
port:
number: 80

View File

@@ -0,0 +1,2 @@
resources:
- ingress.yaml