How to run sidecar container in jenkins pipeline running inside kubernetes

2/8/2019

I need to build and run some tests using a fresh database. I though of using a sidecar container to host the DB.

I've installed jenkins using helm inside my kubernetes cluster using google's own tutorial. I can launch simple 'hello world' pipelines which will start on a new pod.

Next, I tried Jenkin's documentation for running an instance of mysql as a sidecar.

node {
    checkout scm
    docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"') { c ->
        docker.image('mysql:5').inside("--link ${c.id}:db") {
            /* Wait until mysql service is up */
            sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done'
        }
        docker.image('centos:7').inside("--link ${c.id}:db") {
            /*
             * Run some tests which require MySQL, and assume that it is
             * available on the host name `db`
             */
            sh 'make check'
        }
    }
}

At first, it complained that docker was not found, and the internet suggested using a custom jenkins slave image with docker installed.

Now, if I run the pipeline, it just hangs in the loop waiting for the db to be ready.

Disclaimer: New to jenkins/docker/kubernetes

-- Sagi
continuous-deployment
continuous-integration
docker
jenkins
kubernetes

2 Answers

2/11/2019

Eventually I've found this method. It relies on the kubernetes pipeline plugin, and allows running multiple containers in the agent pod while sharing resources.

Note that label should not be an existing label, otherwise when you go to run, your podTemplate will be unable to find the container you made. With this method you are making a new set of containers in an entirely new pod.

def databaseUsername = 'app'
def databasePassword = 'app'
def databaseName = 'app'
def databaseHost = '127.0.0.1'

def jdbcUrl = "jdbc:mariadb://$databaseHost/$databaseName".toString()

podTemplate(
        label: label,
        containers: [
                containerTemplate(
                        name: 'jdk',
                        image: 'openjdk:8-jdk-alpine',
                        ttyEnabled: true,
                        command: 'cat',
                        envVars: [
                                envVar(key: 'JDBC_URL', value: jdbcUrl),
                                envVar(key: 'JDBC_USERNAME', value: databaseUsername),
                                envVar(key: 'JDBC_PASSWORD', value: databasePassword),
                        ]
                ),
                containerTemplate(
                        name: "mariadb",
                        image: "mariadb",
                        envVars: [
                                envVar(key: 'MYSQL_DATABASE', value: databaseName),
                                envVar(key: 'MYSQL_USER', value: databaseUsername),
                                envVar(key: 'MYSQL_PASSWORD', value: databasePassword),
                                envVar(key: 'MYSQL_ROOT_PASSWORD', value: databasePassword)
                        ],
                )
        ]
) {
  node(label) {

      stage('Checkout'){
          checkout scm
      }

      stage('Waiting for environment to start') {
          container('mariadb') {
              sh """
while ! mysqladmin ping --user=$databaseUsername --password=$databasePassword -h$databaseHost --port=3306 --silent; do
    sleep 1
done
"""
          }

      }

      stage('Migrate database') {
          container('jdk') {
              sh './gradlew flywayMigrate -i'
          }
      }

      stage('Run Tests') {
          container('jdk') {
              sh './gradlew test'
          }
      }
  }
}
-- Sagi
Source: StackOverflow

2/8/2019

you should be using kubectl cli (using manifests yaml files)to create those mysql and centos pods,svc and other k8s objects. run tests on mysql database using mysql service dns.

This is how we have tested new database deployments

-- P Ekambaram
Source: StackOverflow