Skip to content

Instantly share code, notes, and snippets.

@javiercr
Last active November 18, 2019 18:09
Show Gist options
  • Save javiercr/fa4335e6bc67147b1e12523b0282a18a to your computer and use it in GitHub Desktop.
Save javiercr/fa4335e6bc67147b1e12523b0282a18a to your computer and use it in GitHub Desktop.
Sample files for "CI/CD with Kubernetes, Helm & Wercker" talk at #madScalability
# deploy/kubernetes-chart/templates/_helpers.tpl
{{- define "toYaml" -}}
{{- range $key, $value := . -}}
{{- $map := kindIs "map" $value -}}
{{- if $map }}
{{ $key }}:
{{- include "toYaml" $value | indent 2 }}
{{- else }}
{{ $key }}: {{ $value }}
{{- end }}
{{- end -}}
{{- end -}}
# deploy/kubernetes-chart/Chart.yaml
name: my-awesome-project
version: 0.1.0
description: MyAwesomeProject chart containing Rails app, PostgreSQL, Redis, Memcached, Resque workers and a cron daeomon
# deploy/kubernetes-chart/templates/db.yaml
apiVersion: v1
kind: Service
metadata:
labels:
name: db
name: db
spec:
ports:
- port: 5432
protocol: TCP
targetPort: 5432
selector:
name: db
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
name: db
name: db-deployment
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
name: db
spec:
containers:
- env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
key: db-user
name: app-env
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
key: db-pass
name: app-env
image: postgres:9.5
imagePullPolicy: Always
name: db
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: my-awesome-project-{{.Values.environment}}-db-storage
restartPolicy: Always
volumes:
- gcePersistentDisk:
fsType: ext4
pdName: my-awesome-project-{{.Values.environment}}-db-disk
name: my-awesome-project-{{.Values.environment}}-db-storage
# deploy/kubernetes-chart/production-values.yaml
environment: production
webReplicas: 2
workerReplicas: 1
resources:
db:
cpu: 1000m
memory: 1.5Gi
secrets:
certs:
tls.crt: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
tls.key: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
appenv:
aws-access-key-id: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
aws-secret-access-key: REPLACE_MEREPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
db-host: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
db-pass: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
db-port: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
db-user: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
rack-env: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
rails-env: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
# deploy/kubernetes-chart/rails_env.yaml
- name: REDIS_URL
value: redis://redis:6379
- name: MEMCACHE_SERVERS
value: memcached
- name: RAILS_ENV
valueFrom:
secretKeyRef:
key: rails-env
name: app-env
- name: RACK_ENV
valueFrom:
secretKeyRef:
key: rack-env
name: app-env
- name: DB_USER
valueFrom:
secretKeyRef:
key: db-user
name: app-env
- name: DB_PASS
valueFrom:
secretKeyRef:
key: db-pass
name: app-env
- name: DB_HOST
valueFrom:
secretKeyRef:
key: db-host
name: app-env
- name: DB_PORT
valueFrom:
secretKeyRef:
key: db-port
name: app-env
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
key: aws-access-key-id
name: app-env
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
key: aws-secret-access-key
name: app-env
# deploy/kubernetes-chart/templates/secrets.yaml
apiVersion: v1
data: {{ include "toYaml" .Values.secrets.appenv | indent 2 }}
kind: Secret
metadata:
name: app-env
type: Opaque
---
apiVersion: v1
data: {{ include "toYaml" .Values.secrets.certs | indent 2 }}
kind: Secret
metadata:
name: certs
type: Opaque
# deploy/kubernetes-chart/staging-values.yaml
environment: staging
webReplicas: 1
workerReplicas: 1
secrets:
certs:
tls.crt: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
tls.key: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
appenv:
aws-access-key-id: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
aws-secret-access-key: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
db-host: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
db-pass: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
db-port: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
db-user: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
rack-env: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
rails-env: REPLACE_ME_WITH_A_BASE64_ENCODED_VALUE
# deploy/kubernetes-chart/templates/web.yaml
apiVersion: v1
kind: Service
metadata:
labels:
name: web
name: web
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
name: web
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: my-awesome-project-{{.Values.environment}}-ip
spec:
backend:
serviceName: web
servicePort: 80
tls:
- secretName: certs
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
name: web
name: web-deployment
spec:
replicas: {{.Values.webReplicas}}
template:
metadata:
labels:
name: web
spec:
containers:
- env:
{{ .Files.Get "rails_env.yaml" | indent 10 }}
image: {{.Values.myAwesomeProjectImage}}
name: rails-app
readinessProbe:
failureThreshold: 3
httpGet:
httpHeaders:
- name: X-Forwarded-Proto
value: https
- name: Host
value: my-awesome-project.com
path: /health_check
port: 80
scheme: HTTP
initialDelaySeconds: 1
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 2
volumeMounts:
- mountPath: /etc/env
name: environment-variables
readOnly: true
resources:
requests:
cpu: 50m
memory: 500Mi
restartPolicy: Always
volumes:
- name: environment-variables
secret:
secretName: app-env
# wercker.yml
box: ruby:2.2
build:
services:
- redis
- postgres
steps:
- install-packages:
packages: nodejs
- kntmrkm/install-phantomjs@1.0.1
- bundle-install:
jobs: 4
- script:
name: rake db:create
code: RAILS_ENV=test rake db:create
- script:
name: rake db:schema:load
code: RAILS_ENV=test rake db:schema:load
- script:
name: rspec
code: bundle exec rspec
- script:
name: Cleanup files
code: rm -rf ./tmp/*
after-steps:
- script:
name: Hipchat nofication
code: |
if [ "$WERCKER_RESULT" = "passed" ]; then
export HIPCHAT_MESSAGE="📦 Build success (<a href='${WERCKER_RUN_URL}'>${WERCKER_GIT_COMMIT}</a>)"
export HIPCHAT_COLOR=green
else
export HIPCHAT_MESSAGE="📦 Build failed! (<a href='${WERCKER_RUN_URL}'>${WERCKER_GIT_COMMIT}</a>)"
export HIPCHAT_COLOR=red
fi
curl -sX POST --data "room_id=Development&from=Wercker&message=$HIPCHAT_MESSAGE&color=$HIPCHAT_COLOR" https://api.hipchat.com/v1/rooms/message?auth_token=$HIPCHAT_TOKEN
build-container:
steps:
# Add required packages for production
- install-packages:
packages: nodejs cron nginx
- script:
name: Copy unicorn config
code: cp ./deploy/unicorn.rb ./config/
- script:
name: Copy nginx config
code: cp ./deploy/nginx.conf /etc/nginx/nginx.conf
# Reinstall gems without development and test
- bundle-install:
jobs: 4
without: development test
- script:
name: rake assets:precompile
code: RAILS_ENV=production bundle exec rake assets:precompile
- script:
name: Cleanup files
code: rm -rf tmp/* .git
- `internal/docker-push`:
cmd: foreman start
working-dir: $WERCKER_SOURCE_DIR
tag: $WERCKER_GIT_COMMIT
username: _json_key
password: $GCP_KEY_JSON
repository: $GCR_TAG
registry: $GCR_HOST
deploy:
steps:
- riceo/kubectl:
name: Install kubectl
gcloud-key-json: $GCP_KEY_JSON
gke-cluster-name: $GCP_CLUSTER_NAME
gke-cluster-zone: europe-west1-d
gke-cluster-project: $GCP_CLUSTER_PROJECT
command: version # this is just to complain with the required argument
- script:
name: Install helm
code: |
mkdir -p helm
curl http://storage.googleapis.com/kubernetes-helm/helm-v2.0.0-beta.1-linux-amd64.tar.gz | tar zxv -C helm
mv helm/linux-amd64/helm /usr/local/bin/helm
helm init -c
- script:
name: Deploying with helm upgrade
code: helm upgrade --install my-awesome-project ./deploy/kubernetes-chart --values ./deploy/kubernetes-chart/$ENV_NAME-values.yaml --set myAwesomeProject=eu.gcr.io/my-awesome-project/my-awesome-project:$WERCKER_GIT_COMMIT
after-steps:
- script:
name: Hipchat nofication
code: |
if [ "$WERCKER_RESULT" = "passed" ]; then
export HIPCHAT_MESSAGE="🚀 Deployed to $ENV_NAME (<a href='${WERCKER_RUN_URL}'>${WERCKER_GIT_COMMIT}</a>)!"
export HIPCHAT_COLOR=green
else
export HIPCHAT_MESSAGE="🚀 Deployment to $ENV_NAME failed! (<a href='${WERCKER_RUN_URL}'>${WERCKER_GIT_COMMIT}</a>)"
export HIPCHAT_COLOR=red
fi
curl -sX POST --data "room_id=Development&from=Wercker&message=$HIPCHAT_MESSAGE&color=$HIPCHAT_COLOR" https://api.hipchat.com/v1/rooms/message?auth_token=$HIPCHAT_TOKEN
# deploy/kubernetes-chart/templates/worker.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
name: worker
name: worker-deployment
spec:
replicas: {{.Values.workerReplicas}}
template:
metadata:
labels:
name: worker
spec:
containers:
- args:
- rake
- environment
- resque:work
- QUEUE=*
- COUNT=1
env:
{{ .Files.Get "rails_env.yaml" | indent 10 }}
image: {{.Values.myAwesomeProjectImage}}
name: resque
volumeMounts:
- mountPath: /etc/env
name: environment-variables
readOnly: true
resources:
requests:
cpu: 30m
memory: 100Mi
limits:
memory: 1Gi
volumes:
- name: environment-variables
secret:
secretName: app-env
@fabito
Copy link

fabito commented Mar 20, 2017

Where do do you define the GCP_KEY_JSON environment variable ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment