Skip to content

Commit

Permalink
Adding quotes sample app for GCS with Istio
Browse files Browse the repository at this point in the history
  • Loading branch information
anouarchattouna committed Mar 22, 2019
1 parent 2f695dc commit 2eec78e
Show file tree
Hide file tree
Showing 10 changed files with 455 additions and 0 deletions.
81 changes: 81 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,83 @@
# gke-service-catalog-sample-gcs
This is a sample application that demonstrates how to use k8s Service Catalog, GCP Service Broker & GCS from a GKE cluster with Istio enabled.

It extends the [quotes](https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/master/service-catalog/cloud-storage) sample application to make it work from an Istio cluster.

## Prerequisites

Successful use of the sample requires:

* A Kubernetes cluster, minimum version 1.8.x.
* Kubernetes Service Catalog and the Google Cloud Platform Service Broker [installed](
https://cloud.google.com/kubernetes-engine/docs/how-to/add-on/service-broker/install-service-catalog).
* The [Service Catalog
CLI](https://github.com/kubernetes-incubator/service-catalog/blob/master/docs/install.md#installing-the-service-catalog-cli)
(`svcat`) installed.
* A running [installation](https://istio.io/docs/setup/kubernetes/) of Istio

## Step 1: Create a Kubernetes namespace
```shell
kubectl apply -f manifests/storage-quotes-namespace.yaml
```

## Step 2: Provisioning Cloud Storage

This sample application is using a single service account for authentication with all Google Cloud services.

* Create the cloud-iam-service-account istance
```shell
kubectl apply -f manifests/gcp-iam-sa/instance.yaml
```
The instance is provisioned when status is `Ready` : ```svcat get instances --namespace storage-quotes```
* Create the binding to the cloud-iam-service-account istance
```shell
kubectl apply -f manifests/gcp-iam-sa/binding.yaml
```
Wait for the binding to be `Ready` : ```svcat get bindings --namespace storage-quotes```
* Once the instance and the binding are `Ready`, make sure to have the following secrets:
```
kubectl get secrets -n storage-quotes
NAME TYPE DATA AGE
gcp-iam-sa-credentials Opaque 2 1h
quotes-gcp-gcs-credentials Opaque 3 1h
```
## Step 3: Deploy the application
```shell
kubectl apply -f manifests/quotes-deployment.yaml
```
## Step 3: Access the application
Now that the application is up and running, we need to make the application accessible from outside of your Kubernetes cluster. An [Istio Gateway](https://istio.io/docs/concepts/traffic-management/#gateways) is used for this purpose.
```shell
kubectl apply -f manifests/quotes-gateway.yaml
```
### Determining the ingress IP and ports
Execute the following command to determine if your Kubernetes cluster is running in an environment that supports external load balancers:
```shell
kubectl get svc istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 172.21.109.129 130.211.10.121 80:31380/TCP,443:31390/TCP,31400:31400/TCP 17h
```
If the EXTERNAL-IP value is set, your environment has an external load balancer that you can use for the ingress gateway.

```$ export GATEWAY_URL=$EXTERNAL-IP```
```shell
# Query the quotes:
curl -s http://${GATEWAY_URL}/quotes
{"quotes":[]}
```
```shell
# Create a new quote:
curl http://${GATEWAY_URL}/quotes -d '{"person": "Dalai Lama", "quote": "Be kind whenever possible. It is always possible."}'

# Query the quotes again:
curl http://${GATEWAY_URL}/quotes
{"quotes":[{"person":"Dalai Lama","quote":"Be kind whenever possible. It is always possible."}]}
```

Et voilà !

## Credits

- [GoogleCloudPlatform/kubernetes-engine-samples](https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/master/service-catalog#application-service-account)
- [istio.io](https://istio.io/docs/reference/config/networking/v1alpha3)
- [istio.io/bookinfo](https://istio.io/docs/examples/bookinfo/)
20 changes: 20 additions & 0 deletions manifests/gcp-gcs-quotes/binding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceBinding
metadata:
name: quotes-gcp-gcs-binding
namespace: storage-quotes
labels:
app.kubernetes.io/name: quotes-gcp-gcs-binding
spec:
instanceRef:
# The name of the service instance to 'bind to'. The act of binding will
# grant the service account specified below specific roles so that it can
# access the Storage service instance with desired privileges.
name: quotes-gcp-gcs-instance
secretName: quotes-gcp-gcs-credentials
parameters:
# The service account which should be granted the storage privileges.
# It is configured from the gcp-iam-sa
serviceAccount: google-cloud-services-sa
roles:
- roles/storage.objectAdmin
17 changes: 17 additions & 0 deletions manifests/gcp-gcs-quotes/instance.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceInstance
metadata:
name: quotes-gcp-gcs-instance
namespace: storage-quotes
labels:
app.kubernetes.io/name: quotes-gcp-gcs-instance
spec:
# This should match with a SERVICE EXTERNAL NAME
# in the list of available services.
clusterServiceClassExternalName: cloud-storage
# This should match with a PLAN EXTERNAL NAME
# in the list of available service plans.
clusterServicePlanExternalName: beta
parameters:
bucketId: quotes-gcp-gcs-instance-bucket
location: europe-west1
14 changes: 14 additions & 0 deletions manifests/gcp-iam-sa/binding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceBinding
metadata:
name: gcp-iam-sa-binding
namespace: storage-quotes
labels:
app.kubernetes.io/name: gcp-iam-sa-binding
spec:
instanceRef:
# The name of the service instance to 'bind to'. The act of binding will
# grant the service account specified below specific roles so that it can
# access the Storage service instance with desired privileges.
name: gcp-iam-sa-instance
secretName: gcp-iam-sa-credentials
19 changes: 19 additions & 0 deletions manifests/gcp-iam-sa/instance.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceInstance
metadata:
name: gcp-iam-sa-instance
namespace: storage-quotes
labels:
app.kubernetes.io/name: gcp-iam-sa-instance
spec:
# This should match with a SERVICE EXTERNAL NAME
# in the list of available services.
clusterServiceClassExternalName: cloud-iam-service-account
# This should match with a PLAN EXTERNAL NAME
# in the list of available service plans.
clusterServicePlanExternalName: beta
parameters:
# The service account name length must be between 6 and 30 characters
# https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/master/service-catalog#application-service-account
accountId: google-cloud-services-sa
displayName: "A service account used to authenticate with all Google Cloud services"
66 changes: 66 additions & 0 deletions manifests/quotes-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
apiVersion: v1
kind: Service
metadata:
name: quotes-service
namespace: storage-quotes
labels:
app: quotes
spec:
selector:
app: quotes
ports:
- port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: quotes-deployment
namespace: storage-quotes
spec:
replicas: 1
selector:
matchLabels:
app: quotes
template:
metadata:
labels:
app: quotes
spec:
volumes:
# Make the 'gcp-iam-sa-credentials' secret available as volume
# 'google-cloud-key'.
- name: google-cloud-key
secret:
secretName: gcp-iam-sa-credentials
containers:
- name: quotes
image: bistov/quotes
volumeMounts:
# Mount the 'google-cloud-key' volume into the container file
# system.
- name: google-cloud-key
mountPath: /var/secrets/google
env:
# Pass the path to the private key JSON file from the mounted volume
# to the environment variable.
- name: "GOOGLE_APPLICATION_CREDENTIALS"
value: /var/secrets/google/privateKeyData
# The two environment variables below come from the 'telemetries-gcp-gcs-credentials'
# secret and, together, point at the Cloud Storage Bucket to use.
- name: "GOOGLE_CLOUD_STORAGE_PROJECT_ID"
valueFrom:
secretKeyRef:
# Use the projectId value from the 'telemetries-gcp-gcs-credentials' secret created
# as a result of binding to the Storage service instance.
name: telemetries-gcp-gcs-credentials
key: projectId
- name: "GOOGLE_CLOUD_STORAGE_BUCKET_ID"
valueFrom:
secretKeyRef:
# Use the topicId value from the 'telemetries-gcp-gcs-credentials' secret created
# as a result of binding to the Storage service instance.
name: telemetries-gcp-gcs-credentials
key: bucketId
ports:
- containerPort: 8080
55 changes: 55 additions & 0 deletions manifests/quotes-gateway.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# https://istio.io/docs/reference/config/networking/v1alpha3/gateway/
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: quotes-gateway
namespace: storage-quotes
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"

---
# https://istio.io/docs/reference/config/networking/v1alpha3/virtual-service/
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: quotes
namespace: storage-quotes
spec:
hosts:
- "*"
gateways:
- quotes-gateway
http:
- route:
- destination:
host: quotes-service
port:
number: 80
match:
- uri:
exact: /quotes

---
# https://istio.io/docs/reference/config/networking/v1alpha3/service-entry/#ServiceEntry
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: google-apis
namespace: storage-quotes
spec:
hosts:
- "*.googleapis.com"
ports:
- number: 443
name: https
protocol: TLS
resolution: NONE
location: MESH_EXTERNAL
6 changes: 6 additions & 0 deletions manifests/storage-quotes-namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
istio-injection: enabled
name: storage-quotes
9 changes: 9 additions & 0 deletions quotes/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM golang:1.12.0-alpine3.9
ADD . /go/src/storage/user
RUN apk add --no-cache git
RUN go get storage/user
RUN go install storage/user
FROM alpine:latest
RUN apk add --no-cache ca-certificates
COPY --from=0 /go/bin/user .
CMD ["/user"]
Loading

0 comments on commit 2eec78e

Please sign in to comment.