diff --git a/docs/development-guide.md b/docs/development-guide.md index 129e6b3e1e4..cfaf3d27405 100644 --- a/docs/development-guide.md +++ b/docs/development-guide.md @@ -79,28 +79,47 @@ This doc explains how to build and run the Online Boutique source code locally u ## Option 2 - Local Cluster -1. Launch a local Kubernetes cluster with one of the following tools: +### Launching with Minikube - - 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 +1. Launch a **Minikube** cluster (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 - ``` + ```shell + minikube start --cpus=4 --memory 4096 --disk-size 32g + ``` + +2. Run `kubectl get nodes` to verify you're connected to the respective control plane. - - 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 +3. Apply the Minikube-specific Kubernetes manifest file: + + ```sh + kubectl apply -f ./release/minikube-kubernetes-manifests.yaml + ``` + + The `minikube-kubernetes-manifests.yaml` file includes changes made to ensure compatibility with Minikube: + + - **Service Type Adjustments**: Services originally defined as `LoadBalancer` have been changed to `NodePort` since Minikube does not natively support `LoadBalancer` services without additional configurations. + - **Resource Requests and Limits** (Optional): CPU and memory resource requests and limits have been reduced to align with the typically constrained resource availability in a Minikube environment. + +4. Run `kubectl get pods` to verify the Pods are ready and running. - - To launch a **Kind** cluster: +5. Run `kubectl get services` to confirm that the services are up and running. - ```shell - kind create cluster - ``` +6. To access the frontend service, you can run the following command, which will open it in your default web browser: + + ```sh + minikube service frontend-external + ``` + +### Launching with Kind + +1. To launch a **Kind** cluster: + + ```shell + kind create cluster + ``` 2. Run `kubectl get nodes` to verify you're connected to the respective control plane. @@ -114,8 +133,7 @@ This doc explains how to build and run the Online Boutique source code locally u 6. Navigate to `localhost:8080` to access the web frontend. - ## Cleanup -If you've deployed the application with `skaffold run` command, you can run +If you've deployed the application with the `skaffold run` command, you can run `skaffold delete` to clean up the deployed resources. diff --git a/release/minikube-kubernetes-manifests.yaml b/release/minikube-kubernetes-manifests.yaml new file mode 100644 index 00000000000..f7313f327e7 --- /dev/null +++ b/release/minikube-kubernetes-manifests.yaml @@ -0,0 +1,978 @@ +# 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. + +# ---------------------------------------------------------- +# WARNING: This file is autogenerated. Do not manually edit. +# ---------------------------------------------------------- + +# [START gke_release_kubernetes_manifests_microservices_demo] +--- +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.2 + 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 +--- +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.2 + 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 # could adjust to 50m (Optional) + memory: 64Mi # could adjust to 32Mi (Optional) + limits: + cpu: 200m # could adjust to 100m (Optional) + memory: 128Mi # could adjust to 64Mi (Optional) +--- +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 +--- +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: us-central1-docker.pkg.dev/google-samples/microservices-demo/recommendationservice:v0.10.2 + 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 +--- +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.2 + 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: NodePort + selector: + app: frontend + ports: + - name: http + port: 80 + targetPort: 8080 +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: frontend +--- +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: us-central1-docker.pkg.dev/google-samples/microservices-demo/paymentservice:v0.10.2 + 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 +--- +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: us-central1-docker.pkg.dev/google-samples/microservices-demo/productcatalogservice:v0.10.2 + 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 +--- +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.2 + 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 +--- +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: us-central1-docker.pkg.dev/google-samples/microservices-demo/loadgenerator:v0.10.2 + env: + - name: FRONTEND_ADDR + value: "frontend:80" + - name: USERS + value: "10" + resources: + requests: + cpu: 300m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: loadgenerator +--- +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.2 + 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 +--- +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: us-central1-docker.pkg.dev/google-samples/microservices-demo/shippingservice:v0.10.2 + 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 +--- +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.2 + 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 +# [END gke_release_kubernetes_manifests_microservices_demo]