Skip to content

Commit

Permalink
DR-306: kubernetes deploy (#87)
Browse files Browse the repository at this point in the history
* updated k8s config
* restructuring
* updating README
  • Loading branch information
ahaessly authored Apr 16, 2019
1 parent 3c3976a commit c633b35
Show file tree
Hide file tree
Showing 20 changed files with 290 additions and 299 deletions.
64 changes: 50 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,76 @@ The repo for the terra data repository built by the jade team.

See the DATABASE.md to set up the postgres database before you run jade.

## Setup environment
### Google project and account
You must have authenticated with google for application-default credentials:

## Create kubernetes cluster

In the google cloud console, within your personal project, go to Kubernetes Engine -> Clusters and create a cluster. In the default pool section change nodes to 1 and click node pool options. Change boot disk size to 10G. At the bottom of the page, click the Advanced section and click the checkbox to enable VPC native. Then click create.

Once your cluster has finished creating, click the Connect button next to you cluster info. Copy the command and execute it on your local system. Now, if you click on docker -> kubernetes you should see a check next to the cluster you just created.


## Create a service account
In the google cloud console, go to IAM & Admin -> Service accounts. Click create service account. Choose a name and add a description (this service account will be used to manage big query and postgres data for the datarepo).

Give your service account access to dev GCR:

gsutil iam ch serviceAccount:jade-k8-sa@${PROJECT}.iam.gserviceaccount.com:objectViewer gs://artifacts.broad-jade-dev.appspot.com

Grant your service account the storage and bigquery admin roles:

gcloud projects add-iam-policy-binding ${PROJECT} --member serviceAccount:jade-k8-sa@${PROJECT}.iam.gserviceaccount.com --role roles/bigquery.admin
gcloud projects add-iam-policy-binding ${PROJECT} --member serviceAccount:jade-k8-sa@${PROJECT}.iam.gserviceaccount.com --role roles/storage.admin

## Deploying to kubernetes
### Deploying in your own test account (not dev, integration, etc)
#### Environment variables
GOOGLE_CLOUD_PROJECT
ENVIRONMENT (local, dev)

Add the service account key for your project to vault:

vault write secret/dsde/firecloud/local/datarepo/sa-key${PROJECT}.json @<localfilename>.json

Deploy:

./ops/deploy.sh

After you deploy, go to Kubernetes in the google cloud console, select services, and then add the IP address of the oidc-proxy-service to your /etc/hosts file as `jade.datarepo-dev.broadinstitute.org`

## Build and Run Locally

### Set up
You must have authenticated with google for application-default credentials:

gcloud auth application-default login
and login with an account that has access to your project. This will save credentials locally. If you are using multiple accounts, you can switch to the correct one using this command:
and login with an account that has access to your project. This will save credentials locally. If you are using multiple accounts, you can switch to the correct one using this command:

gcloud config set account <account email>

Then you must specify a google project to use. Either run this command:
Then you must specify a google project to use. Run this command:


gcloud config set project <project-name>

or specify your project in the environment variable: `GOOGLE_CLOUD_PROJECT`.


To see what you currently have set, use: `gcloud config list`

### OIDC Environment variables
When running locally, we are not using the proxy. Therefore, the system doesn't know your user email. Edit the `src/main/resources/application.properties` file and set the userEmail field. If you are running sam locally, set `sam.basePath` to `https://local.broadinstitute.org:50443`.

### Environment variables

There are some secrets that need to be provided to the app and will not be checked in
to github. If you are standing this up on your own, you will need to get an Oauth client
id and secret. We got one in GCP from the cloud console by creating an
[Oauth consent screen](https://console.cloud.google.com/apis/credentials/consent)
and then an [Oauth web client id](https://console.cloud.google.com/apis/credentials).
to github. If you are standing this up on your own, you will need to set the following environment variables to the values [here](https://console.cloud.google.com/apis/credentials/oauthclient/970791974390-1581mjhtp2b3jmg4avhor1vabs13b7ur.apps.googleusercontent.com?project=broad-jade-dev&organizationId=548622027621)

OAUTH_CLIENT_ID
OAUTH_CLIENT_SECRET

## Build and Run
### Run unit tests

If you are making code changes, run:
`./gradlew check`

### Run jade locally

To run jade locally:
`./gradlew bootRun`

Expand Down
7 changes: 4 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ dependencies {
compile 'org.apache.directory.studio:org.apache.commons.io:2.4'
compile 'org.apache.commons:commons-dbcp2:2.5.0' // For database connection support
compile 'org.postgresql:postgresql:42.2.5' // Postgres jdbc driver
compile 'com.google.cloud:google-cloud-bigquery:1.65.0'
compile 'com.google.cloud:google-cloud-storage:1.65.0'
compile 'com.google.cloud:google-cloud-bigquery:1.66.0'
compile 'com.google.cloud:google-cloud-storage:1.66.0'
compile 'org.liquibase:liquibase-core:3.6.1' // For upgrade
compile 'org.slf4j:slf4j-api:1.7.25' // Logging facade
compile 'ch.qos.logback:logback-classic:1.2.3' // Logger
Expand Down Expand Up @@ -240,8 +240,9 @@ def getGitHash = { ->
return stdout.toString().trim()
}


docker {
name "gcr.io/broad-jade-dev/${bootJar.baseName}:${getGitHash()}"
name "gcr.io/broad-jade-dev/${bootJar.baseName}:latest${System.env.GOOGLE_CLOUD_PROJECT}"
copySpec.from(tasks.unpack.outputs).into("dependency")
buildArgs(['DEPENDENCY': "dependency"])
}
Expand Down
85 changes: 85 additions & 0 deletions ops/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/bin/bash

set -e

# Prerequisites:
# - Docker (https://www.docker.com/products/docker-desktop)
# - Homebrew (https://brew.sh/)

# check to make sure vault and cloud env vars are set correctly
# these commands below check to make sure that an environment variable is set to a non-empty thing
: ${GOOGLE_CLOUD_PROJECT:?}
: ${VAULT_ADDR:?}
: ${ENVIRONMENT:?}

if [ -z "$VAULT_TOKEN" ]; then
if [ ! -f ~/.vault-token ]; then
echo "VAULT_TOKEN needs to be set or ~/.vault-token needs to exist"
exit 1
fi
export VAULT_TOKEN=$( cat ~/.vault-token )
fi

# the paths we'll use will be relative to this script
WD=$( dirname "${BASH_SOURCE[0]}" )
SCRATCH=/tmp/deploy-scratch

# Install kubectl
command -v kubectl >/dev/null 2>&1 || {
echo "kubectl not found, installing";
brew install kubernetes-cli;
}

# Install consul-template (note this didn't work with 0.20.0, I kept getting 403 errors)
command -v consul-template >/dev/null 2>&1 || {
echo "consul-template not found, installing";
curl https://releases.hashicorp.com/consul-template/0.19.5/consul-template_0.19.5_darwin_386.tgz | tar xzv;
mv consul-template /usr/local/bin/;
}

# make a temporary directory for rendering, we'll delete it later
mkdir -p $SCRATCH

# create a data-repo namespace to put everything in
kubectl apply -f "${WD}/k8s/namespace.yaml"

# render secrets, create or update on kubernetes
consul-template -template "${WD}/k8s/secrets/api-secrets.yaml.ctmpl:${SCRATCH}/api-secrets.yaml" -once
kubectl apply -f "${SCRATCH}/api-secrets.yaml"

# update the service account key
vault read "secret/dsde/firecloud/${ENVIRONMENT}/datarepo/sa-key${GOOGLE_CLOUD_PROJECT}.json" -format=json | jq .data > "${SCRATCH}/sa-key.json"
kubectl --namespace data-repo get secret sa-key && kubectl --namespace data-repo delete secret sa-key
kubectl --namespace data-repo create secret generic sa-key --from-file="sa-key.json=${SCRATCH}/sa-key.json"

# set the tsl certificate
vault read -field=value secret/dsp/certs/wildcard.datarepo-dev.broadinstitute.org/20210326/server.crt > "${SCRATCH}/server.crt"
vault read -field=value secret/dsp/certs/wildcard.datarepo-dev.broadinstitute.org/20210326/server.key > "${SCRATCH}/server.key"
kubectl get secret tls-cert && kubectl delete secret tls-cert
kubectl create secret tls tls-cert --cert=${SCRATCH}/server.crt --key=${SCRATCH}/server.key

# create or update postgres pod + service
kubectl apply -f "${WD}/k8s/pods/psql-pod.yaml"
kubectl apply -f "${WD}/k8s/services/psql-service.yaml"

# wait for the db to be ready so that we can run commands against it
kubectl wait --for=condition=Ready -f "${WD}/k8s/pods/psql-pod.yaml"

# create the right databases/user/extensions (TODO: moving this to be the APIs responsibility soon)
cat "${WD}/../db/create-data-repo-db" | \
kubectl --namespace data-repo run psql -i --restart=Never --rm --image=postgres:9.6 -- psql -h postgres-service -U postgres

# build a docker container and push it to gcr
${WD}/../gradlew dockerPush

# create or update the api pod + service
kubectl apply -f "${WD}/k8s/deployments/api-deployment.yaml"
kubectl apply -f "${WD}/k8s/services/api-service.yaml"

kubectl --namespace data-repo set image deployments/api-deployment "data-repo-api-container=gcr.io/broad-jade-dev/jade-data-repo:latest${GOOGLE_CLOUD_PROJECT}"

# create or update oidc proxy pod + service, probably need to render secrets
kubectl apply -f "${WD}/k8s/deployments/oidc-proxy-deployment.yaml"
kubectl apply -f "${WD}/k8s/services/oidc-proxy-service.yaml"

rm -r $SCRATCH
77 changes: 77 additions & 0 deletions ops/k8s/deployments/api-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
namespace: data-repo
spec:
replicas: 1
selector:
matchLabels:
component: data-repo-api
template:
metadata:
labels:
app: data-repo
component: data-repo-api
spec:
volumes:
- name: google-cloud-key
secret:
secretName: sa-key
containers:
- name: data-repo-api-container
image: gcr.io/broad-jade-dev/jade-data-repo:latest
volumeMounts:
- name: google-cloud-key
mountPath: /var/secrets/google
ports:
- containerPort: 8080
- containerPort: 5005
env:
- name: GOOGLE_APPLICATION_CREDENTIALS
value: /var/secrets/google/sa-key.json
- name: OAUTH_CLIENT_ID
valueFrom:
secretKeyRef:
name: api-secrets
key: oauth-client-id
- name: GOOGLE_CLOUD_PROJECT
valueFrom:
secretKeyRef:
name: api-secrets
key: google-cloud-project
- name: DB_DROP_ALL_ON_START
valueFrom:
secretKeyRef:
name: api-secrets
key: drop-all-on-start
- name: DB_DATAREPO_URI
valueFrom:
secretKeyRef:
name: api-secrets
key: datarepo-uri
- name: DB_DATAREPO_USERNAME
valueFrom:
secretKeyRef:
name: api-secrets
key: datarepo-username
- name: DB_DATAREPO_PASSWORD
valueFrom:
secretKeyRef:
name: api-secrets
key: datarepo-password
- name: DB_STAIRWAY_URI
valueFrom:
secretKeyRef:
name: api-secrets
key: stairway-uri
- name: DB_STAIRWAY_USERNAME
valueFrom:
secretKeyRef:
name: api-secrets
key: stairway-username
- name: DB_STAIRWAY_PASSWORD
valueFrom:
secretKeyRef:
name: api-secrets
key: stairway-password
38 changes: 38 additions & 0 deletions ops/k8s/deployments/oidc-proxy-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: oidc-proxy-deployment
namespace: data-repo
spec:
replicas: 1
selector:
matchLabels:
component: data-repo-oidc-proxy
template:
metadata:
labels:
app: data-repo
component: data-repo-oidc-proxy
spec:
containers:
- name: oidc-proxy-container
image: broadinstitute/openidc-proxy:db_ldap_2_3_3
env:
- name: PROXY_URL
value: 'http://ui-service.data-repo:80/'
- name: PROXY_URL2
value: 'http://api-service.data-repo:8080/api'
- name: PROXY_URL3
value: 'http://api-service.data-repo:8080/register'
- name: CALLBACK_URI
value: 'https://jade.datarepo-dev.broadinstitute.org/oauth2callback'
- name: LOG_LEVEL
value: 'debug'
- name: SERVER_NAME
value: 'jade.datarepo-dev.broadinstitute.org'
- name: REMOTE_USER_CLAIM
value: 'sub'
- name: ENABLE_STACKDRIVER
value: 'yes'
- name: FILTER2
value: 'AddOutputFilterByType DEFLATE application/json text/plain text/html application/javascript application/x-javascript'
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ metadata:
name: api-secrets
namespace: data-repo
data:
drop-all-on-start: {{ .Data.dropAllOnStart | base64Encode }}
datarepo-uri: {{ .Data.datarepoUri | base64Encode }}
datarepo-username: {{ .Data.datarepoUsername | base64Encode }}
datarepo-password: {{ .Data.datarepoPassword | base64Encode }}
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ metadata:
namespace: data-repo
name: oidc-proxy-service
spec:
type: LoadBalancer
selector:
component: data-repo-oidc-proxy
ports:
Expand Down
File renamed without changes.
50 changes: 0 additions & 50 deletions ops/kubernetes/deployment.yaml

This file was deleted.

11 changes: 0 additions & 11 deletions ops/kubernetes/secrets.yaml

This file was deleted.

Loading

0 comments on commit c633b35

Please sign in to comment.