Skip to content

Instantly share code, notes, and snippets.

@romdim
Created March 22, 2017 12:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save romdim/0acfcf367d24dfb6aff26d58e8b24955 to your computer and use it in GitHub Desktop.
Save romdim/0acfcf367d24dfb6aff26d58e8b24955 to your computer and use it in GitHub Desktop.
apiVersion: v1
kind: Secret
metadata:
name: drone-secrets
type: Opaque
data:
server.secret: REPLACE-THIS-WITH-BASE64-ENCODED-VALUE

Drone on Google Container Engine (minimal example)

This directory contains an example of a simple but production-ready Drone install on Google Container Engine. We use nginx and Let's Encrypt to automatically generate a matching SSL cert for you at runtime.

Note: While Drone supports a variety of different remotes, this demo assumes that the projects you'll be building are on GitHub.

Prep work

**Warning: Before proceeding, you should have followed the directions in the "Prep Work" section in the README.md found in this directory's parent.

Install Drone

Finally, run install-drone.sh and follow the prompts carefully. At the end of the installation script, you should be able to point your browser at https://drone.your-fqdn.com and see a Login page.

Compromises Made

This install script installs Drone on the cluster that is currently active in your kubectl client, in whatever namespace your current active context specifies (the default namespace if you haven't done anything to specifically change it). This is fine if Drone is the only thing running on your cluster, and is often fine even if that is not the case.

If you'd like to further isolate Drone from anything else running on your cluster, see the Kubernetes docs for Sharing a Cluster with Namespaces. Before installing Drone, you'd want to create a new namespace, configure your kubectl context, set the context as active, then run the install script.

Troubleshooting

You can verify that everything is running correctly like this:

kubectl get pods

You should see several pods in a "Running" state. If there were issues, note the name of the pod and look at the logs. This is a close approximation of what you'd need to type to check the nginx proxy logs:

kubectl logs -f drone-server-a123 nginx-proxy

Here's a close approximation of what you'd need to check the Drone server logs:

kubectl logs -f drone-server-a234 drone-server

And agent:

kubectl logs -f drone-agent-a345

Where drone-server-a123 is the pod name.

Stuck? Need help?

We've glossed over quite a few details, for the sake of brevity. If you have questions, post them to our Help! category on the Drone Discussion site. If you'd like a more realtime option, visit our Gitter room.

apiVersion: v1
kind: ReplicationController
metadata:
name: drone-agent
labels:
heritage: drone-demos
spec:
replicas: 1
selector:
name: drone-agent
template:
metadata:
labels:
name: drone-agent
spec:
containers:
- image: drone/drone:0.5
imagePullPolicy: Always
name: drone-agent
command:
- "/drone"
- "agent"
env:
- name: I_UNDERSTAND_I_AM_USING_AN_UNSTABLE_VERSION
value: "true"
- name: I_AGREE_TO_FIX_BUGS_AND_NOT_FILE_BUGS
value: "true"
- name: DRONE_DEBUG
valueFrom:
configMapKeyRef:
name: drone-config
key: agent.debug.is.enabled
- name: DRONE_SERVER
valueFrom:
configMapKeyRef:
name: drone-config
key: agent.drone.server.url
- name: DRONE_SECRET
valueFrom:
secretKeyRef:
name: drone-secrets
key: server.secret
resources:
requests:
cpu: 100m
memory: 64Mi
volumeMounts:
# Enables Docker in Docker
- mountPath: /var/run/docker.sock
name: docker-socket
volumes:
- name: docker-socket
hostPath:
path: /var/run/docker.sock
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-03-30T21:14:38Z
name: drone-config
namespace: default
data:
################
# Proxy Config #
################
# CHANGEME: This should be changed to a valid email for Let's Encrypt's
# records.
proxy.letsencrypt.email: your@email.com
# CHANGEME: The Fully-Qualified Domain Name (FQDN) for where Drone will run.
# No need to create a DNS entry just yet. The installer will walk you through
# this process.
proxy.fqdn: drone.yourdomain.com
################################
# Drone Server (master) Config #
################################
server.debug.is.enabled: "true"
# You'll probably want to leave this alone, but you can point to external
# DB instances if you'd like: http://readme.drone.io/0.5/manage/database/
server.database.driver: sqlite3
server.database.config: /var/lib/drone/drone.sqlite
server.is.open: "true"
# CHANGEME: If you want to restrict access to a particular org, put the
# name here.
server.orgs.list: ""
# CHANGEME: Add your GitHub/Bitbucket/Gogs/etc username here. This is a
# comma-separated list of usernames who will have admin privs.
server.admin.list: admin,users,here
server.admin.everyone.is.admin: "false"
# See http://readme.drone.io/0.5/manage/server/ for possible values here.
# For now, our demo is GitHub-only. Drone supports other remotes, we just
# haven't set the others up in here yet.
# CHANGEME: Substitute your Github OAuth application client ID and secret.
server.remote.github.is.enabled: "true"
server.remote.github.client.id: xxxxxxxxxxxxxxxxxxxx
server.remote.github.secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
######################
# Drone Agent Config #
######################
agent.debug.is.enabled: "true"
# CHANGEME: Change this to point to the same FQDN as proxy.fqdn above.
agent.drone.server.url: wss://drone.yourdomain.com/ws/broker
apiVersion: v1
kind: ReplicationController
metadata:
name: drone-server
labels:
heritage: drone-demos
spec:
replicas: 1
selector:
name: drone-server
template:
metadata:
labels:
name: drone-server
spec:
containers:
- image: yurifl/nginx-for-drone:latest
imagePullPolicy: Always
name: nginx-proxy
env:
- name: DOMAIN
valueFrom:
configMapKeyRef:
name: drone-config
key: proxy.fqdn
- name: EMAIL
valueFrom:
configMapKeyRef:
name: drone-config
key: proxy.letsencrypt.email
- name: UPSTREAM
value: localhost:8000
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
resources:
requests:
cpu: 40m
memory: 12Mi
- image: drone/drone:0.5
imagePullPolicy: Always
name: drone-server
env:
- name: DRONE_SERVER_ADDR
value: ":8000"
- name: I_UNDERSTAND_I_AM_USING_AN_UNSTABLE_VERSION
value: "true"
- name: I_AGREE_TO_FIX_BUGS_AND_NOT_FILE_BUGS
value: "true"
- name: DRONE_DEBUG
valueFrom:
configMapKeyRef:
name: drone-config
key: server.debug.is.enabled
- name: DRONE_SECRET
valueFrom:
secretKeyRef:
name: drone-secrets
key: server.secret
- name: DRONE_DATABASE_DRIVER
valueFrom:
configMapKeyRef:
name: drone-config
key: server.database.driver
- name: DRONE_DATABASE_DATASOURCE
valueFrom:
configMapKeyRef:
name: drone-config
key: server.database.config
- name: DRONE_OPEN
valueFrom:
configMapKeyRef:
name: drone-config
key: server.is.open
- name: DRONE_ORGS
valueFrom:
configMapKeyRef:
name: drone-config
key: server.orgs.list
- name: DRONE_ADMIN
valueFrom:
configMapKeyRef:
name: drone-config
key: server.admin.list
- name: DRONE_ADMIN_ALL
valueFrom:
configMapKeyRef:
name: drone-config
key: server.admin.everyone.is.admin
- name: DRONE_GITHUB
valueFrom:
configMapKeyRef:
name: drone-config
key: server.remote.github.is.enabled
- name: DRONE_GITHUB_CLIENT
valueFrom:
configMapKeyRef:
name: drone-config
key: server.remote.github.client.id
- name: DRONE_GITHUB_SECRET
valueFrom:
configMapKeyRef:
name: drone-config
key: server.remote.github.secret
ports:
- containerPort: 8000
protocol: TCP
volumeMounts:
# Persist our configs in an SQLite DB in here
- mountPath: /var/lib/drone
name: drone-server-sqlite-db
# Enables Docker in Docker
- mountPath: /var/run/docker.sock
name: docker-socket
resources:
requests:
cpu: 40m
memory: 32Mi
volumes:
- name: drone-server-sqlite-db
gcePersistentDisk:
pdName: drone-server-sqlite-db
fsType: ext4
- name: docker-socket
hostPath:
path: /var/run/docker.sock
apiVersion: v1
kind: Service
metadata:
name: drone-server
labels:
provider: drone-server
heritage: drone-demos
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
- name: https
port: 443
protocol: TCP
targetPort: 443
selector:
name: drone-server
type: LoadBalancer
#!/usr/bin/env bash
kubectl cluster-info > /dev/null 2>&1
if [ $? -eq 1 ]
then
echo "kubectl was unable to reach your Kubernetes cluster. Make sure that" \
"you have selected one using the 'gcloud container' commands."
exit 1
fi
# Clear out any existing configmap. Fail silently if there are none to delete.
kubectl delete configmap drone-config 2> /dev/null
if [ $? -eq 1 ]
then
echo "Before continuing, make sure you've opened drone-configmap.yaml and" \
"changed the values commented with CHANGEME in the comments."
echo
read -p "<Press enter once you've made your edits>"
fi
# If secrets.yaml isn't present, we'll auto-generate the Drone secret and
# upload it via kubectl.
if ! [ -f "secrets.yaml" ];
then
echo "secrets.yaml not present. Randomly generating and uploading..."
drone_token=`cat /dev/urandom | env LC_CTYPE=C tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
b64_drone_token=`echo -n $drone_token | base64`
sed "s/REPLACE-THIS-WITH-BASE64-ENCODED-VALUE/${b64_drone_token}/g" .secrets.yaml.tpl > secrets.yaml
else
kubectl delete secrets drone-secrets 2> /dev/null
fi
kubectl create -f secrets.yaml
kubectl create -f drone-server-svc.yaml 2> /dev/null
if [ $? -eq 0 ]
then
echo "Since this is your first time running this script, we have created a" \
"front-facing Load Balancer with an external IP. You'll need to wait" \
"for the LB to initialize and pull an IP address. We'll pause for a" \
"bit and walk you through this after the break."
while true; do
echo "Waiting for 60 seconds for LB creation..."
sleep 60
echo "[[ Querying your drone-server service to see if it has an IP yet... ]]"
echo
kubectl describe svc drone-server
echo "[[ Query complete. ]]"
read -p "Do you see a 'Loadbalancer Ingress' field with a value above? (y/n) " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) echo "We'll give it some more time.";;
* ) echo "No idea what that was, but we'll assume yes!";;
esac
done
echo
echo "Excellent. Create a DNS (A) Record that matches the value you entered" \
"for proxy.fqdn in drone-configmap.yaml. It should point at the IP you" \
"see above next to 'Loadbalancer Ingress'. Once you have configured the" \
"DNS entry, don't proceed until nslookup is showing the IP you set." \
"Let's Encrypt needs to be able to resolve and send a request to your " \
"server in order to verify service and generate the cert."
read -p "<Press enter to proceed once nslookup is resolving your proxy FQDN>"
fi
kubectl delete rc drone-server 2> /dev/null
kubectl create -f drone-configmap.yaml
kubectl create -f drone-server-rc.yaml
echo
echo "===== Drone Server installed ============================================"
echo "Your cluster is now downloading the Docker image for Drone Server."
echo "You can check the progress of this by typing 'kubectl get pods' in another"
echo "tab. Once you see 2/2 READY for your drone-server-* pod, point your browser"
echo "at https://<your-fqdn-here> and you should see a login page."
echo
echo "If you have picked a slower machine type (g1-small), certificate"
echo "generation time can take up to a minute or so. If you are seeing"
echo "connection failure errors, give it up to two minutes before getting"
echo "too concerned. If your server never becomes reachable, refer to the"
echo "Troubleshooting section in the gke-with-https README.md."
echo
read -p "<Press enter once you've verified that your Drone Server is up>"
echo
echo "===== Drone Agent installation =========================================="
kubectl delete rc drone-agent 2> /dev/null
kubectl create -f drone-agent-rc.yaml
echo "Your cluster is now downloading the Docker image for Drone Agent."
echo "You can check the progress of this by typing 'kubectl get pods'"
echo "Once you see 1/1 READY for your drone-agent-* pod, your Agent is ready"
echo "to start pulling and running builds."
echo
read -p "<Press enter once you've verified that your Drone Agent is up>"
echo
echo "===== Post-installation tasks ==========================================="
echo "At this point, you should have a fully-functional Drone install. If this"
echo "Is not the case, stop by either of the following for help:"
echo
echo " * Gitter (realtime chat): https://gitter.im/drone/drone"
echo " * Discussion Site, help category: https://discuss.drone.io/c/help"
echo
echo "You'll also want to read the documentation: https://readme.drone.io"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment