Updated on 2026-03-10 GMT+08:00

Implementing Continuous Integration and Deployment

In this solution, a code push event triggers Jenkins to compile and package the application. After the application is approved via email, it is deployed in a Kubernetes cluster.

Installing Jenkins Plug-ins

In addition to the default plug-ins installed during Jenkins installation, you need to install the GitLab, Kubernetes CLI, and Email Extension Template plugins. For details, see the Jenkins official documentation.

On the Jenkins dashboard page, click Manage Jenkins on the left and choose System Configuration > Manage Plugins. On the Available tab, search for GitLab, Kubernetes CLI, and Email Extension Template, and install them.

The versions of these plug-ins may change over time.

Configuring a GitLab Webhook

Once you push your code, GitLab will notify Jenkins of the event using webhooks. To ensure this process runs smoothly, you must first configure GitLab hooks.

  1. Log in to Jenkins, click New Item, and create a pipeline.

  2. Copy the URL and click Advanced.

  3. Click Generate to generate a token, record the token, retain the default values for other parameters, and save the settings.

  4. Log in to GitLab and enable webhooks.

    Allow requests to the local network. To enhance security, GitLab 10.6 and later versions prohibit webhook requests from being sent to any local network.

  5. Log in to the java-demo project on GitLab, choose Settings > Webhooks, and enter the values recorded in Jenkins in URL and Secret token.

  6. At the bottom of the page, confirm that the webhook has been added and perform tests.

Configuring Email Notifications

Jenkins often uses email for message notifications and approvals. This solution also employs email as the approval method.

  1. On the Manage Jenkins page, select System.

  2. Configure basic mailbox information and enter the email address of the administrator.

    The password is not the email password but the email authorization code.

Configuring a Credential

Accessing Kubernetes clusters through HTTPS is crucial for maintaining security. To achieve this, you must configure the credentials for accessing clusters on Jenkins.

  1. Obtain the kubeconfig configuration of the Kubernetes cluster client. For details, see Accessing a Cluster Using kubectl.
  2. Log in to Jenkins, click Manage Jenkins, choose Manage Credentials under Security, and create a cluster credential using the secret file.

  3. Repeat the preceding steps to create an access credential for the production cluster.

Writing Pipeline Scripts

Pipeline is a workflow framework that operates within Jenkins. It links tasks that would typically run independently on one or more nodes, allowing for the orchestration and visualization of complex processes that cannot be completed by a single task. It is the primary feature of Jenkins 2.X and enables Jenkins to transition from CI to CD and DevOps. Consequently, the writing of pipeline scripts is crucial to the successful implementation of the entire solution.

The concepts of pipeline scripts are shown below.

  • Node

    A node is a machine which is part of the Jenkins environment and is capable of executing a pipeline.

  • Stage

    A stage block defines a group of specific tasks to be executed in different stages such as the build, test, and deploy stages through the entire pipeline.

  • Step

    A step is a single task in a stage, such as running a test or deploying code. It tells Jenkins what to do at a specific time, for example, to execute the shell command. For more Jenkins pipeline syntax, see the Jenkins official documentation.

  1. Go to the Jenkins pipeline and click Configuration in the navigation pane.
  2. Configure the pipeline scripts. The pipeline scripts shown below are for reference only. You can customize the scripts based on your service requirements.

    Some parameters in the example need to be changed.

    • git_url: specifies the SSH address of a code repository in GitLab. You need to replace it with the actual value.
    • swr_login: The login command is the command obtained in 3.
    • swr_region: specifies the region of SWR. You need to specify the region as needed.
    • organization: specifies the actual organization name in SWR.
    • build_name: specifies the name of the created image.
    • test_credential: specifies the testing cluster credential added to Jenkins. You need to enter the credential ID. To deploy the service in another cluster, add the access credential of the cluster to Jenkins again. For details, see cluster access credential configurations.
    • prod_credential: specifies the production cluster credential added to Jenkins. You need to enter the credential ID. To deploy the service in another cluster, add the access credential of the cluster to Jenkins again. For details, see cluster access credential configurations.
    • test_apiserver: specifies the API server address of a testing cluster. For details, see Accessing a Cluster Using kubectl. You have to ensure that the address can be accessed from the Jenkins cluster.
    • prod_apiserver: specifies the API server address of a production cluster. For details, see Accessing a Cluster Using kubectl. You have to ensure that the address can be accessed from the Jenkins cluster.
    • test_email: specifies the email address of the test personnel.
    • admin_email: specifies the email address of the approver.
    #!groovy
    // Define the code repository address.
    def git_url = 'ssh://git@xxxx:222/ccedemo/java-demo.git' 
    // Define the SWR login command.
    def swr_login = 'docker login -u cn-north-4@xxxx -p xxxxxx swr.cn-north-4.myhuaweicloud.com'
    // Define the SWR region.
    def swr_region = 'cn-north-4'
    // Specify the name of an SWR organization to which images are pushed.
    def organization = 'testapp'
    // Define the image name.
    def build_name = 'demo01'
    // Certificate ID of a testing cluster
    def test_credential = 'test_config'
    // Certificate ID of a production cluster
    def prod_credential = 'prod_config'
    // API server address of a testing cluster. You have to ensure that the address can be accessed from the Jenkins cluster.
    def test_apiserver = 'https://xxx:5443'
    // API server address of a production cluster. You have to ensure that the address can be accessed from the Jenkins cluster.
    def prod_apiserver = 'https://xxxx:5443'
    // Email addresses
    def test_email="xxxxx@xx.com"
    def admin_email="xxxx@xx.com"
    
    pipeline{
    agent any
    stages{
        stage('Git code'){
            steps{
                echo "1. Git code" 
                git url: git_url
                script { 
                    // Specify the return value of git rev-parse --short HEAD as the commit ID, which is then used as the image tag.
                    build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() 
                    image_url = "swr.${swr_region}.myhuaweicloud.com/${organization}/${build_name}:${build_tag}"  
                    } 
                }
        }
        stage('Build') {
            steps{
                echo "2. Build Docker Image Stage and Push Image" 
                sh "docker build -t  ${image_url} ." 
                sh swr_login
                sh "docker push ${image_url}"
                // Replace the image URL with that in the Kubernetes resource file.
                sh  "sed -i 's+demo01:v1+${image_url}+g' ./demo01.yaml"
            }
        }
        stage('Deploy Test Environment') {
            steps{
                // Configure the testing environment certificate.
                echo "3. Deploy Test Environment"
                script {
                    try {
                        withKubeConfig([credentialsId: test_credential, serverUrl: test_apiserver]) {
                            sh 'kubectl apply -f ./demo01.yaml'
                            // The YAML file is stored in the code repository. It is only used as an example here, so you need to replace it as required.
                        }
                        println "deploy success"
                        // Send an email to the test personnel.
                        mail subject: "[Please Test] The application has been deployed in the test environment. Please start the test.",
                        body: """After the test is passed, <a href="${BUILD_URL}input">click the link and use the account to log in to the system. The test is successful.</h3>""",
                        charset: 'utf-8',
                        mimeType: 'text/html',
                        to: "$test_email"
                    } catch (e) {
                        RUN_FLAG = false
                        println "deploy failed!"
                        println e
                    }
                }
            }
        }
        stage('Test'){
            // Wait for the test confirmation.
            input{ 
                message "Test Passed or Not"
                submitter "admin"
            }
            steps{
                script{
                    println "4. Test Passed"
                    // Send an email to the administrator.
                    mail subject: "[Please Approve] Release to the production environment",
                    body: """The test is passed, <a href="${BUILD_URL}input">Click the link and use the account to log in to the system for approval.</h3>""",
                    charset: 'utf-8',
                    mimeType: 'text/html',
                    to: "$test_email"
                }
            }
        }
        stage('Approve'){
            input{ 
                message "Release to Production Environment or Not"
                submitter "admin" 
            }
            steps{
                script{
                    println "5. Approved and released it to the production environment."
                }
            }
        }
        stage('Deploy Produce Environment'){
            steps{
                echo "6. Deploy Produce Environment"
                script {
                    try {
                        withKubeConfig([credentialsId: prod_credential, serverUrl: prod_apiserver]) {
                            sh 'kubectl apply -f ./demo01.yaml'
                            // The YAML file is stored in the code repository. It is only used as an example here, so you need to replace it as required.
                        }
                        println "deploy success"
                    } catch (e) {
                        println "deploy failed!"
                        println e
                    }
                }
            }
        }
    }

  3. Save the changes to complete the configurations of the entire project.

Configuring Continuous Build and Deployment

  1. Modify the local code and submit it to trigger compilation.

    git add . && git commit -m "add template" && git push

  2. Go back to the Jenkins page.

    You can see that the project has automatically triggered compilation and builds.

  3. Wait for several minutes. You will receive a test email.

  4. Log in to the testing cluster and verify that the java-demo workload has been created.

  5. Click the link in the email to confirm the test. In this example, the upgrade test is considered to pass.

  6. (For the approver) Receive an email requesting approval.

  7. (For the approver) Determine that the service can be deployed in the production environment, click the link, and agree to the request.

  8. Access the production cluster console and verify that the java-demo workload has been created and released in the production environment.