Deploying from Travis-CI to Google Container Engine
Travis-ci is a great CI tool. In comparison to other solutions, it has the advantage of being free for Open Source projects and is well documented.
This is why I’ve been using it for a while and more recently with regexrace, a project hosted in Google Container Engine cluster. Since Kubernetes abstracts much of the deployment and management processes, the only thing we have to handle is how to trigger the deployment.
Which is incredibly simple once you’ve setup the gcloud CLI :
kubectl apply -f my_replica_controller_config.yml
kubectl rolling-update my_replica_controller --image=gcr.io/my_project/my_project:the_project_version --image-pull-policy Always
But if you try to create a bash script and trigger it from Travis you may encounter these errors :
Unable to connect to the server: dial tcp <your_cluster_ip>: i/o timeout
# OR
error: You must be logged in to the server (the server has asked for the client to provide credentials)
To get rid of these errors, we’ll have to ensure kubectl is using the right credentials every time we use it.
If you didn't set up travis yet
To set up gcloud in Travis and push the Docker build to Google Container Registry, you should either read the good article of Scott Smerchek or (the very-fast way), to copy/paste the following lines and set up the related environment variables in your Travis project settings :
cache:
directories:
- "$HOME/google-cloud-sdk/"
after_success:
- if [ ! -d "$HOME/google-cloud-sdk/bin" ]; then rm -rf $HOME/google-cloud-sdk; curl https://sdk.cloud.google.com | bash; fi
# Add gcloud to $PATH
- source /home/travis/google-cloud-sdk/path.bash.inc
- gcloud version
- gcloud --quiet components update kubectl
# Auth flow
- echo $GCLOUD_KEY | base64 --decode > gcloud.p12
- gcloud auth activate-service-account $GCLOUD_EMAIL --key-file gcloud.p12
- ssh-keygen -f ~/.ssh/google_compute_engine -N ""
# Push to Google container registry
- docker build -t gcr.io/$CLOUDSDK_CORE_PROJECT/$CLOUDSDK_CORE_PROJECT:v1 .
- gcloud docker push gcr.io/$CLOUDSDK_CORE_PROJECT/$CLOUDSDK_CORE_PROJECT:v1 > /dev/null
- gcloud container clusters get-credentials $CLOUDSDK_CORE_PROJECT
Related environment variables :
Env variables | Content |
---|---|
GCLOUD_KEY | base64-encoded version of project_name-xxxxx.json |
GCLOUD_EMAIL | {string_of_characters}@developer.gserviceaccount.com |
CLOUDSDK_CORE_DISABLE_PROMPTS | 1 |
CLOUDSDK_CORE_PROJECT | your_project_name_on_gcloud |
CLOUDSDK_COMPUTE_ZONE | us-east1-b (for example) |
GKE_USERNAME | the_cluster_username |
GKE_PASSWORD | the_cluster_password |
GKE_SERVER | the_cluster_ip |
Let's fix the kubectl command
After getting all of these errors, I tried to get some debug logs and looked into the gcloud manual pages and Github issues. Finally, I found an explanation on a Github issue and one of the last comment of zeg-io.
Your ~/.kube/config is missing some value for authentication. To resolve this, run the command below on your gcloud shell (Google Console): $ export GOOGLE_APPLICATION_CREDENTIALS=”/path/to/keyfile.json”
Next, you’ll need to run the get-credentials command below again to fetch credentials for a running cluster. $ gcloud container clusters get-credentials project-cluster-1 –zone us-central1-c
Then, you may now run ‘kubectl proxy’ command again and let me know if you’re still having trouble.
So,
gcloud container clusters get-credentials $CLOUDSDK_CORE_PROJECT
requires you to store a JSON file containing the credentials.
As we have it stored in the $GCLOUD_KEY
environment variable and we decoded it into a gcloud.p12
file, we can set the content of $GOOGLE_APPLICATION_CREDENTIALS
to the path of that file.
For example :
$GOOGLE_APPLICATION_CREDENTIALS="/home/travis/gopath/src/github.com/thylong/regexrace/gcloud.p12"
The final result can be seen here.
Enjoy ! Don’t hesitate to comment / open pull requests or issues on the regexrace project.