Hello, and welcome to my first blog post!
Today we’re going to look into what is required to deploy a hexo site to a kubernetes cluster.
In this post we take a closer look at Dockerizing applications, Kubernetes deployment files and Gitlab CI Jobs to do these things for us.
Requirements
We’re going to use the following tools:
- jojoxd/deploy-tools
- A set-up Kubernetes cluster managed by GitLab
- GitLab CI Runner
Before getting started
A note on my Docker Repository;
My Docker repository is located at docker.jojoxd.nl:5005
, which is a GitLab default instance. you should change this to your own server wherever you find it in this post.
Getting started
First, we’re going to create a hexo project
1 | hexo init 'jojoxd-nl' |
This should push the site to your gitlab instance. (it should automatically create the repository.)
Generating Site Content
Firstly, we have to create a gitlab CI job to generate the content using hexo.
1 | # |
When you git push
this, it should generate an artifact with your site content.
Setting up Kubernetes deployment files
The Kubernetes files are templates, just like in Helm, but we don’t have any fancy if statements and such, it is only variable substitution.
deploy-tools uses envsubst
internally to “template” the files.
Service
The service file groups multiple pods from a deployment together under a single Service.
1 | # |
Notice that we use CI_ENVIRONMENT_SLUG
as a prefix in metadata.name
, this allows GitLab to monitor the resource and ingress usage for the site.
Note: you can use your own domain for the
ref
annotation, e.g.ref.my-domain.org: ${LABEL_REF}
Deployment
The Deployment actually deploys the Docker image to your Kubernetes cluster.
1 | # |
Securing the image repository
Note: This will only work with Gitlab Docker Registry
Create a Deploy Token
for your project, you can find it in Project Settings > Repository > Deploy Tokens
It MUST be named gitlab-deploy-token
, or it won’t be available in your CI environment
You MUST do this step if your project is set to private or protected.
Patch the following files:
1 | # |
1 |
|
This will generate a Secret
containing the deploy-key you created in GitLab.
Ingress
The ingress connects the service to a domain
1 | # |
Deployment
Containerizing your site
To run your site in Kubernetes, you need to create a Docker image.
This is very easy to do; we only need to have a webserver and the generated files for it.
1 | # |
Building Container using GitLab CI
We’re going to use GitLab CI to create and push our app container to the container repository.
The complete .gitlab-ci.yml
can be found at the end of this tutorial
1 | # |
We add a dependency on generate-content
, so the public
artifact will be re-downloaded from GitLab.
Otherwise, the job could be run on a different runner, where the folder is not available, and the build will therefore fail.
You should
git push
this so you can check if your container is being built correctly
Testing the container
Before continuing, we’re going to test the container using Docker.
1 | docker run --rm -p 8080:80 -t docker.jojoxd.nl:5005/jojoxd-k8s/jojoxd-nl:master |
You should now be able to see the site using localhost:8080
Setting up deploy-tools
For the deployment, we’re going to use deploy-tools, my own feature-poor bash-implemented version of helm.
1 | # In the jojoxd-nl folder |
Creating deploy script
The deploy-script should be in the root of your repository. (I named it deploy.sh
)
Firstly, we should load the deploy-tools.sh file
1 | source $(which deploy-tools.sh || echo "k8s/deploy-tools/deploy-tools.sh") |
We specify it with a which
first, as we’re not going to setup GitLab to pull submodules, and instead use the Docker image provided by deploy-tools to gain access to the tools and kubectl
.
Next up, we ensure all our environment variables are set.
We use the CI_*
variables to be able to track our deployments using an annotation later.
1 | env::exists KUBE_NAMESPACE |
Next up, we’re going to call kubectl to push all our configuration to the cluster.
1 |
|
If you want to use imagePullSecrets, add that now
Locally testing deployment using minikube
It’s always a good idea to test your deployment before pushing it to your production server; let’s use minikube to deploy it to a freshly created cluster.
Note: You should push your changes (including your .gitlab-ci.yml with the release step) to the server, So you can use the generated Docker image.
1 | minikube start |
If you get an error that the script can’t source deploy-tools,
you might need to rungit submodule update --init
before retrying
If everything is right, you should see that the namespace, deployment, service and ingress are created in the dashboard.
To access your deployment, look at the ingress IP, and add the following to your
/etc/hosts
file:<ingress-ip> jojoxd.local
You should now be able to connect to jojoxd.local
in your browser.
Note: You might need to disable HSTS in the browser to be able to view the site.
Setting up Deployment using Gitlab CI
For GitLab to deploy your site, it should only need to call deploy.sh.
1 | # |
Commit this, let the compile & release run, and click the play button on this new stage.
It should now push your site to your cluster.