DEV Community

Cover image for Deploy static front-end application to kubernetes cluster using Jenkins CD and minio with automatic https cert
pongsatt
pongsatt

Posted on

Deploy static front-end application to kubernetes cluster using Jenkins CD and minio with automatic https cert

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

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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")
        }
    }

  }

}
Enter fullscreen mode Exit fullscreen mode

From the configuration, I have a Jenkins build agent with label "docker" that contains "kubernetes" and "mc" cli.

There are 3 stages.

  1. build: react project to "build" folder
  2. publish to minio: copy folder "build" to minio "public/simpleapp"
  3. 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)

Collapse
 
sacha_smart_2ccd888dc7f19 profile image
Sacha Smart

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.