After we've setup kubernetes cluster on our VMs, we setup nginx ingress automatically apply for certificate with letsencrypt. This post we will deploy static web application using Jenkins CD and minio.
With Jenkins CD, we can define our build and deployment pipeline, and with the power of kubernetes and docker, our application infrastructure also defined along with our source code.
With minio, a file storage server, we can host static web site as a folder like we do with AWS S3 but within our own infrastructure.
Then with nginx ingress that we setup from previous post, we can point website URL to minio file serving.
Note:
This post assume that you follow this series of posts
If you follow this series, you need to be on master node to follow this post
Prerequisite:
- A running kubernetes cluster
- helm installed
- Jenkins server with pipeline support
Setup minio
Note:
minio requires access key and secret. Please replace "myaccesskey" and "mysecret" with you own values
1. Install minio using helm
This run will install minio server in "minio" namespace
helm install --name minio --namespace minio stable/minio \
--set accessKey=myaccesskey,secretKey=mysecret \
--set service.type=NodePort
2. Install minio web client
Install mc cli using command below (need root password).
wget https://dl.minio.io/client/mc/release/linux-amd64/mc && chmod +x mc && sudo mv mc /usr/local/bin/mc
3. Configure minio pointing to the server
Run kubectl get service -n minio
to find NodePort.
Run command to add minio configuration folder.
Note:
Replace with your real master node IP address
Replace with real node port from above step
Replace "myaccesskey" and "mysecret" with your own values
mc config host add myminio http://<Master Node IP>:<NodePort> myaccesskey mysecret
Result should look like this.
4. Create minio folder to host static files
In this example, we will create a bucket name "public" to host all static folders.
mc mb -p myminio/public
mc policy download myminio/public
Run mc ls myminio
and you should see an empty bucket.
Setup DNS record
In order to apply for https domain certificate, you need to set your DNS record "simpleapp.yourdomain.com" to your ingress service IP. You can see my example from previous post.
Build a static website
We will use react application as our sample static website. Let's build it.
1. Initialize application
Note: you will need nodejs installed on your machine.
npx create-react-app simpleapp
cd simpleapp
npm start
Open "http://localhost:3000" and you should see.
2. Add kubernetes ingress configuration
Add "ingress.yml" under "k8s" folder at the root folder.
Content:
Note:
Replace "simpleapp.yourdomain.com" with real domain
This example use "dns01" protocol to acquire letsencrypt certificate. You can change it to "http01" by comment/uncomment
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: simpleapp-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
# use http01 protocol. uncomment line below to use http01
# kubernetes.io/tls-acme: "true"
# use dns01 protocol. comment 2 lines below if use http01
certmanager.k8s.io/acme-challenge-type: "dns01"
certmanager.k8s.io/acme-dns01-provider: "aws-route53"
nginx.ingress.kubernetes.io/rewrite-target: "/public/simpleapp"
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite ^/?$ /public/simpleapp/index.html break;
spec:
tls:
- hosts:
- simpleapp.yourdomain.com
secretName: simpleapp-tls
rules:
# The host must be identical to the above one
- host: simpleapp.yourdomain.com
http:
paths:
- path: /
backend:
# The name of your service
serviceName: minio
servicePort: 9000
This configuration will point "simpleapp.yourdomain.com" to a folder under "public" bucket on minio to a folder name "simpleapp". Also support redirect from "/" to "/index.html"
3. Add Jenkinsfile pipeline
Create file name "Jenkinsfile" at the root folder.
Content:
pipeline {
environment {
ENV = "minio"
APP = "simpleapp"
}
agent { label 'docker' }
stages {
stage('build') {
steps {
withDockerContainer('node:8.4.0-alpine') {
sh 'yarn install'
sh 'yarn build'
}
}
}
stage('publish to minio') {
steps {
sh "mc cp -r build/ myminio/public/${APP}"
}
}
stage('deploy ingress to kubernetes') {
steps {
sh("kubectl --namespace=${ENV} apply -f k8s/ingress.yml")
}
}
}
}
From the configuration, I have a Jenkins build agent with label "docker" that contains "kubernetes" and "mc" cli.
There are 3 stages.
- build: react project to "build" folder
- publish to minio: copy folder "build" to minio "public/simpleapp"
- deploy ingress to kubernetes: deploy "k8s/ingress.yml" to cluster
4. Publish to git repo
You can publish your project to any git repository.
Prepare Jenkins environment
In this example, your jenkins needs to support below cli.
- kubectl : with ".kube" configuration folder that point to our kubernetes server
- mc : with ".mc" configuration folder that point to our minio instance
Note:
Install these tools will depend on your jenkins environment
1. kubectl configuration
You can just copy "~/.kube/config" from master node to "/home/jenkins/.kube/config".
2. mc configuration
You can just copy "~/.mc/config.json" from master node to "/home/jenkins/.mc/config.json"
If all the configurations is ok, you should be able to run command below inside Jenkins agent.
Build Jenkins pipeline
In this example, we will create Jenkins pipeline that point to Jenkinsfile in the repository.
1. Create Jenkins pipeline project
Create "simpleapp" project.
Enter your git repo url and credential.
2. Build pipeline
Normally, pipeline build should be automatically triggered when the source code is update. This example will use manual trigger.
Build result.
Test your application
Wait until kubectl get secret -n minio
return secret name "simpleapp-tls".
If everything is ok, you should be able to open URL "https://simpleapp.yourdomain.com" and see result as below.
Summary
We build static website with Jenkins CD, then deploy to minio file server and kubernetes with automatic letsencrpyt certified. Next, we will do CD with backend code and kubernetes cluster.
Top comments (1)
Very useful article. I’m trying to replicate something similar and I’m having difficulty getting minion to work. I’m fairly new to Jenkins and am used to GitHub actions.
Could you please point in the right direction on how to configure or add minio/mc to an agent within a helm chart? Is it just creating a new Dockerfile and adding these dependencies, then pulling the image onto the agent with the dependencies? Appreciate all the help.