Recently, a colleague and I had to spike on the possibility of migrating our CI/CD infrastructure from a VM based design to a Kubernetes based one.
While exploring how to do it, we had to spend some time to find out all the information we needed just to install and configure GoCD without the migration. So I decided to write this post hoping someone like me would find it helpful.
Creating a Cluster
You can create the cluster using multiple options. You can use
- google-cloud-sdk
- GKE UI interface
- terraform
You can specify the zone, GKE master version, the machine type and number of nodes among other things as per your requirements. Remember to allocate enough vCPUs and RAM to run the GoCD server as well as the agents.
Deploy GoCD
GoCD provides a helm chart to deploy GoCD easily in a cluster. You can also find a basic tutorial here which I’m repeating for better continuity.
1) First you have to set the correct context so that we are able to deploy GoCD in the correct cluster.
gcloud container clusters get-credentials <CLUSTER-NAME> —- zone
<ZONE-NAME> —- project <PROJECT-NAME>
2) Once the correct context is set, helm needs to be installed. If you don’t have it in your machine, install it using one of the many options that helm offers. Then helm needs to be installed on the cluster. This can be done as
helm init
This will install Tiller which is the server side component of Helm on your cluster.
3) Next we need to create a cluster role binding with the kube-system service account.
kubectl create clusterrolebinding clusterRoleBinding \
--clusterrole=cluster-admin \
--serviceaccount=kube-system:default
4) Now we add the repository where the GoCD chart is available as follows.
helm repo add gocd https://gocd.github.io/helm-chart
5) Now, all we have to do is just install the chart as
helm install gocd/gocd —- name gocd —- namespace gocd
This will install GoCD on your server along with an ingress to allow access to the Go server over the internet.
GoCD Public IP Address
You can use the following command to get the IP address of the Go server
kubectl get ingress --namespace gocd gocd-server -o jsonpath=
"{.status.loadBalancer.ingress[0].ip}"
If you go to the server you’ll be able to see the GoCD dashboard with a hello-world pipeline executed just to verify if everything works.
But executing the above command configures the Go server using the values available in this values.yaml file. If you are just playing around to get a feel of using GoCD in Kubernetes, this is fine. However if you are trying to configure the GoCD server with some basic options, then it’s better to use your own values.yaml file as follows
helm install —- name gocd-app —- namespace gocd -f values.yaml gocd/gocd
Configuring Password File based Authentication
For our usecase we needed to add password based authentication in GoCD. Password based authentication is available in GoCD as a built-in plugin called Password File Authentication Plugin. The plugin uses a password file to authenticate whose location can be configured.
The GoCD helm chart allows us to mount volumes using secrets. We can make use of this to mount the password file to a specific location. For example if your password file name is go-password, before installing the GoCD helm chart, you can create a secret in the gocd namespace in the cluster as
kubectl create secret generic go-password \
--from-file=go-password=go-password \
--namespace=gocd
Then you can go to the server.persistence.extraVolumes section and add the secret as
extraVolumes:
- name: go-password-volume-name
secret:
secretName: go-password
defaultMode: 0744
This will create a volume (go-password-volume-name) from the given secret name (go-password). Now you can mount the volume to any location you want in the server.persistence.extraVolumeMounts section as follows
extraVolumeMounts:
- name: go-password-volume-name
mountPath: /etc/go
readOnly: true
This will mount the volume to the /etc/go location. You can now install the GoCD helm chart using the above modified values in the values.yaml.
An important point to note is that this will only mount the password file in the given location. It will NOT enable password based authentication directly. To enable this, you need to add a new Authorization Configuration. This can be configured using either the UI or using a POST request.
- To use the UI to configure this, you can refer here. Make sure to provide the Password file path correctly. In our case it will be /etc/go/go-password
- To use a POST request, you can use this cURL command
curl "https://$gocd_public_ip/go/api/admin/security/auth_configs" \
-H 'Accept: application/vnd.go.cd.v1+json' \
-H 'Content-Type: application/json' \
-X POST -d '{
"id": "passwordfile",
"plugin_id": "cd.go.authentication.passwordfile",
"properties": [
{
"key": "PasswordFilePath",
"value": "/etc/go/go-password"
}
]
}'
You can change the $gocd_public_ip with your GoCD dashboard public IP. You can get this IP from the GoCD Public IP Address section above.
Configuring Access to GitHub for GoCD Server
Since we had all of our code hosted in GitHub, we also needed the GoCD server to have access to our GitHub repositories. One of the most used ways to give access to GitHub is SSH. The values.yaml file allows us to specify a secret that will contain the necessary SSH key files. For more information on generating SSH keys, you can refer here. For GoCD, the three files i.e id_rsa, id_rsa.pub and known_hosts have to be copied to the /etc/go/.ssh folder. This is because GoCD operates with a username called go.
Once you have created these three files you can create a kubernetes secret as
echo "Creating SSH secret to allow access to our Git Repos"
kubectl create secret generic gocd-server-ssh \
--from-file=id_rsa=ssh/id_rsa \
--from-file=id_rsa.pub=ssh/id_rsa.pub \
--from-file=known_hosts=ssh/known_hosts \
--namespace=gocd
This creates a secret gocd-server-ssh in the cluster’s gocd namespace. We can then specify this secret in the server.security.ssh section as follows
security:
ssh:
# server.security.ssh.enabled is the toggle to enable/disable mounting of ssh secret on GoCD server pods
enabled: true
# server.security.ssh.secretName specifies the name of the k8s secret object that contains the ssh key and known hosts
secretName: gocd-server-ssh
Configuring Access to GitHub for GoCD Agent
Just because the GoCD Server has access doesn’t mean that it’s corresponding GoCD agents will also have access. Access for agents has to be configured separately. This is similar to configuring for the server. You can specify the secret name in the agent.security.ssh section as follows
security:
ssh:
# agent.security.ssh.enabled is the toggle to enable/disable mounting of ssh secret on GoCD agent pods
enabled: true
# agent.security.ssh.secretName specifies the name of the k8s secret object that contains the ssh key and known hosts
secretName: gocd-agent-ssh
Note: This will work only if you use static GoCD agents that are always running. It will NOT work if you use elastic agents via elastic agent profiles.
So there you go. I hope you find it useful. If you have any questions, please feel free to comment and I’ll answer from whatever I’ve learnt so far.
*This post was originally published on Mohamed Najiullah's blog.