Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Ray Tsang committed Apr 17, 2018
0 parents commit 34998c1
Show file tree
Hide file tree
Showing 117 changed files with 13,828 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .gitignore
@@ -0,0 +1,21 @@
# Maven
target/

# Eclipse
.settings/
.classpath
.project

# IntelliJ IDEA
.idea
*.iml

# Branch switching
generated/

.DS_Store

**/.*.sw?
**/*.NOT_READY
.json
.env
13 changes: 13 additions & 0 deletions LICENSE
@@ -0,0 +1,13 @@
Copyright 2002-2017 the original author or authors.

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.
183 changes: 183 additions & 0 deletions README.md
@@ -0,0 +1,183 @@
# Google Cloud Native Spring Boot PetClinic

Example Petclinic deployment on Google Cloud Platform into Google Kubernetes Engine with Istio.
This is based on [Spring PetClinic Microservices](https://github.com/spring-petclinic/spring-petclinic-microservices)

This example has:
- Observability and Monitoring
- Stackdriver Trace
- Stackdriver Monitorning
- Stackdriver Logging
- Stackdriver Debugging
- Stackdriver Profiling
- Spring Boot Petclinic Example with Google Cloud Native configuration
- Spring Cloud GCP
- Removed Eureka, Hystrix, Ribbon, Config Server, Gateway, and many other components, because they are provided by Kubernetes and Istio.
- Eureka -> Kubernetes Service
- Config Server -> Kubernetes Config Map
- Gateway -> Kubernetes Ingress
- Hystrix -> Istio
- Ribbon -> Istio
- Build
- Spotify's dockerfile-maven-plugin
- DevOps
- Travis CI

## Google Cloud Platform Project
Create a new Project if you haven't done so already.
```
$ export PROJECT_ID=...
$ gcloud project create $PROJECT_ID
```

Set the default Project ID:
```
$ gcloud config set core/project $PROJECT_ID
```

## Kubernetes Engine Cluster
Use `gcloud` to provision a multi-zone Kubernetes Engine cluster.

```
$ gcloud services enable compute.googleapis.com container.googleapis.com
$ CLOUDSDK_CONTAINER_USE_V1_API_CLIENT=false
$ gcloud container clusters create petclinic-cluster \
--cluster-version=1.9.6 \
--region=us-central1 \
--num-nodes=2 \
--machine-type=n1-standard-2 \
--enable-autorepair \
--no-enable-cloud-logging \
--no-enable-cloud-monitoring
```

## Istio
Install the basics:
```
$ ISTIO_VERSION=0.7.1
$ curl -L https://git.io/getLatestIstio | sh -
$ cd istio-$ISTIO_VERSION
$ kubectl apply -f install/kubernetes/istio.yaml --as=admin --as-group=system:masters
```

Update Sidecar Injector to limit Istio to 10.0.0.0/8 network:
1. Open `install/kubernetes/istio-sidecar-injector-configmap-release.yaml`
1. Update the `initContainers` `args` block:
```
...
initContainers:
- name: istio-init
image: docker.io/istio/proxy_init:0.7.1
args:
- "-p"
- {{ .MeshConfig.ProxyListenPort }}
- "-u"
- 1337
# ADD THE FOLLOWING LINES
- -i
- 10.0.0.0/8
# ADD THE ABOVE LINES
...
```

Install Sidecar Injector:
```
$ istio-$ISTO_VERSION/install/kubernetes/webhook-create-signed-cert.sh \
--service istio-sidecar-injector \
--namespace istio-system \
--secret sidecar-injector-certs
$ kubectl apply -f install/kubernetes/istio-sidecar-injector-configmap-release.yaml
$ cat install/kubernetes/istio-sidecar-injector.yaml | \
./install/kubernetes/webhook-patch-ca-bundle.sh > \
install/kubernetes/istio-sidecar-injector-with-ca-bundle.yaml
$ kubectl apply -f install/kubernetes/istio-sidecar-injector-with-ca-bundle.yaml
Enable Sidecar Injector on `default` namespace:
```
$ kubectl label namespace default istio-injection=enabled
```
## Spanner
```
$ gcloud spanner instances create petclinic --config=regional-us-central1 --nodes=1 --description="PetClinic Spanner Instance"
$ gcloud spanner databases create petclinic --instance=petclinic
$ gcloud spanner databases ddl update petclinic --instance=petclinic --ddl="$(<petclinic/db/spanner.ddl)"
```
## Debugging and Profiling
```
$ gcloud services enable cloudprofiler.googleapis.com clouddebugger.googleapis.com
```
## Generate Service Account
Create a new Service Account for the microservices:
```
$ gcloud iam service-accounts create petclinic --display-name "PetClinic Service Account"
```
Grant IAM Roles to the Service Account:
```
$ gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:petclinic@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/cloudprofiler.agent
$ gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:petclinic@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/clouddebugger.agent
$ gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:petclinic@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/cloudtrace.agent
$ gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:petclinic@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/spanner.databaseUser
```
Create a new JSON Service Account Key. Keep it secure!
```
$ gcloud iam service-accounts keys create ~/petclinic-service-account.json \
--iam-account petclinic@$PROJECT_ID.iam.gserviceaccount.com
```
## Build
### Compile and Install to Maven
```
$ mvn install
```
### Build Docker Images
Build all images:
```
$ mvn package install -PbuildDocker
```
Build just one image:
```
$ mvn package install -PbuildDocker -pl spring-petclinic-customers-service
```
## Run
### Docker Compose
Update `docker-compose.yml` file so that `secrets.petclinic-credentials.file`
points to the JSON file.
Run everything:
```
$ echo "PROJECT_ID=$PROJECT_ID" > .env
$ docker-compose up
```
### Kubernetes
Store Service Account as a Kubenetes Secret:
```
$ kubectl create secret generic petclinic-credentials --from-file=$HOME/petclinic-service-account.json
```
Deploy Application:
```
$ kubectl apply -f kubernetes/petclinic.yaml
```
Deploy Route Rules:
```
$ kubectl apply -f istio/api-routes.yaml
```
36 changes: 36 additions & 0 deletions db/spanner.ddl
@@ -0,0 +1,36 @@
CREATE TABLE owners (
owner_id STRING(36) NOT NULL,
first_name STRING(128) NOT NULL,
last_name STRING(128) NOT NULL,
address STRING(256) NOT NULL,
city STRING(128) NOT NULL,
telephone STRING(20) NOT NULL
) PRIMARY KEY (owner_id);

CREATE TABLE pets (
owner_id STRING(36) NOT NULL,
pet_id STRING(36) NOT NULL,
name STRING(128),
birth_date DATE,
type STRING(16)
) PRIMARY KEY (owner_id, pet_id),
INTERLEAVE IN PARENT owners ON DELETE CASCADE;

CREATE TABLE vets (
vet_id STRING(36) NOT NULL,
first_name STRING(128) NOT NULL,
last_name STRING(128) NOT NULL,
specialties ARRAY<STRING(32)>
) PRIMARY KEY (vet_id);

CREATE INDEX vets_by_last_name ON vets(last_name);

CREATE TABLE visits (
owner_id STRING(36) NOT NULL,
pet_id STRING(36) NOT NULL,
visit_id STRING(36) NOT NULL,
date DATE,
description STRING(MAX)
) PRIMARY KEY (owner_id, pet_id, visit_id),
INTERLEAVE IN PARENT pets ON DELETE CASCADE;

52 changes: 52 additions & 0 deletions docker-compose.yml
@@ -0,0 +1,52 @@
version: '3.6'
secrets:
petclinic-credentials:
file: /home/docker-user/petclinic-service-account.json
services:
customers-service:
image: saturnism/gcp-spring-petclinic-customers-service
container_name: customers-service
environment:
- PROJECT_ID
- GOOGLE_APPLICATION_CREDENTIALS=/run/secrets/petclinic-credentials
secrets:
- petclinic-credentials
ports:
- 8081:8080

visits-service:
image: saturnism/gcp-spring-petclinic-visits-service
container_name: visits-service
environment:
- PROJECT_ID
- GOOGLE_APPLICATION_CREDENTIALS=/run/secrets/petclinic-credentials
secrets:
- petclinic-credentials
ports:
- 8082:8080

vets-service:
image: saturnism/gcp-spring-petclinic-vets-service
container_name: vets-service
environment:
- PROJECT_ID
- GOOGLE_APPLICATION_CREDENTIALS=/run/secrets/petclinic-credentials
secrets:
- petclinic-credentials
ports:
- 8083:8080

api-gateway:
image: saturnism/gcp-spring-petclinic-api-gateway
container_name: api-gateway
links:
- customers-service
- visits-service
- vets-service
environment:
- PROJECT_ID
- GOOGLE_APPLICATION_CREDENTIALS=/run/secrets/petclinic-credentials
secrets:
- petclinic-credentials
ports:
- 8080:8080
4 changes: 4 additions & 0 deletions docker/.dockerignore
@@ -0,0 +1,4 @@
**/*
!*.jar
!lib
!lib/*
43 changes: 43 additions & 0 deletions docker/Dockerfile
@@ -0,0 +1,43 @@
FROM openjdk:8-jre
MAINTAINER Ray Tsang

# Download Cloud Debugger and Cloud Profiler agents
RUN mkdir -p /opt/debugger && \
wget -qO- https://storage.googleapis.com/cloud-debugger/compute-java/debian-wheezy/cdbg_java_agent_service_account.tar.gz | \
tar xvz -C /opt/debugger
RUN mkdir -p /opt/profiler && \
wget -qO- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz | \
tar xvz -C /opt/profiler

# Copy a startup script that helps executing entrypoint with environmental variable
COPY start.sh /app/start.sh
RUN chmod a+x /app/start.sh
ENTRYPOINT ["/app/start.sh"]

# Copy Application, separating dependencies from application code
ADD lib/* /app/lib/
ARG ARTIFACT_FILE
ADD ${ARTIFACT_FILE} /app/app.jar

ARG EXPOSED_PORT=8080
EXPOSE ${EXPOSED_PORT}

ENV SPRING_PROFILES_ACTIVE docker
ARG SERVICE_NAME
ENV SERVICE_NAME ${SERVICE_NAME}

ARG SERVICE_VERSION
ENV SERVICE_VERSION ${SERVICE_VERSION}

# Add Cloud Debugger and Cloud Profiler agents to startup command line
CMD ["java", \
"$JAVA_OPTS", \
"-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap", \
"-agentpath:/opt/debugger/cdbg_java_agent.so", \
"-agentpath:/opt/profiler/profiler_java_agent.so=-cprof_service=$SERVICE_NAME,-cprof_service_version=$SERVICE_VERSION,-cprof_project_id=$PROJECT_ID", \
"-Dcom.google.cdbg.auth.serviceaccount.enable=true", \
"-Dcom.google.cdbg.module=$SERVICE_NAME", \
"-Dcom.google.cdbg.version=$SERVICE_VERSION", \
"-Djava.security.egd=file:/dev/./urandom", \
"-jar","/app/app.jar"]

2 changes: 2 additions & 0 deletions docker/start.sh
@@ -0,0 +1,2 @@
#!/bin/bash
/bin/bash -l -c "$*"

0 comments on commit 34998c1

Please sign in to comment.