DevOps | Software Automation | Continuous Integration

Category: Docker

Top 10 DevOps Tools Or Services Used

Below are the list of top 10 tools I use on a daily basis in my job

  1. Configuration management tool

Configuration management tool – Ansible takes up 80% to 90% of my daily life. All servers provisioning, software installation and management are automated using it. Automation with configuration management tool allows repetition on multiple servers and avoids human error.

2. Jenkins

All software compilation, build and deploys are automated on Jenkins. Includes, writing Jenkins pipeline, installing, upgrading Jenkins and its plugins.

3. AWS

This is where all the servers and resources are. EC2, DNS and other services like Elastic Search etc.

4. Terraform

This is used in to provision the services and resources in AWS. I view it as the configuration management tool of AWS that allows repetition and eliminates human error.

5. Elastic Search

This is where all the logs go to. Maintenance work such as automating snapshot, backup and curator clean up are part of the job.

6. Operating system

System administrating work on operating systems like Ubuntu. Diagnosing, troubleshooting issues, installing and upgrading packages.

7. Nginx

Load balancing for applications and services.

8. Docker

Containerization has become important these days due to cost savings, therefore most servers are shifted towards being provisioned in Docker.

9. Monitoring tools

Integrating monitoring software into the applications, services and databases using services such as New Relic, AppDynamics and Datadog.

10. Hashicorp Vault

Used to store all secrets and sensitive information of applications.

Docker – Jenkins – Get Sensitive Data From AWS SSM

Introduction

For Dockerized Jenkins, we can use the following method to store/get sensitive data from AWS SSM instead of hardcoding it in Docker file

Store secret in AWS SSM:

aws ssm put-parameter –name “artifactory_password” –value “thisisapassword” –type “String”

In Dockerfile:

COPY settings.xml /etc/maven/settings.xml

COPY jenkins-slave /home/jenkins
RUN chmod -R 755 /home/jenkins/jenkins-slave

In settings.xml

<settings xmlns=”http://maven.apache.org/SETTINGS/1.0.0″ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd”>
  <servers>
    <server>
      <id>artifactory_password</id>
      <username>username</username>
      <password>blank</password>
    </server>

</servers>
  <pluginGroups> <pluginGroup>com.amashchenko.maven.plugin.ondeck</pluginGroup>
  </pluginGroups>
</settings>

In jenkins-slave


#!/bin/bash


# The MIT License
#
#  Copyright (c) 2015, CloudBees, Inc.
#
#  Permission is hereby granted, free of charge, to any person obtaining a copy
#  of this software and associated documentation files (the “Software”), to deal
#  in the Software without restriction, including without limitation the rights
#  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#  copies of the Software, and to permit persons to whom the Software is
#  furnished to do so, subject to the following conditions:
#
#  The above copyright notice and this permission notice shall be included in
#  all copies or substantial portions of the Software.
#
#  THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#  THE SOFTWARE.


# take from https://github.com/cloudbees/jnlp-slave-with-java-build-tools-dockerfile/blob/master/jenkins-slave
# assumed that these env vars are present on the kubernetes slave


if [[ $# -eq 1 ]]; then


    # if `docker run` only has one arguments, we assume user is running alternate command like `bash` to inspect the image
    exec “$@”


else


    # if -tunnel is not provided try env vars
    if [[ “$@” != *”-tunnel “* ]]; then
        if [[ ! -z “$JENKINS_TUNNEL” ]]; then
            TUNNEL=”-tunnel $JENKINS_TUNNEL”        
        fi
    fi


    if [[ ! -z “$JENKINS_URL” ]]; then
        URL=”-url $JENKINS_URL”
    fi


    sed -i “s/blank/$(aws ssm get-parameters –region us-east-1 –with-decryption –names artifactory_password –query ‘Parameters[0].Value’ –output text )/” /etc/maven/settings.xml
   
    gosu jenkins java $JAVA_OPTS -Duser.home=/var/lib/jenkins -cp /home/jenkins/slave.jar hudson.remoting.jnlp.Main -headless $URL $JENKINS_SECRET $JENKINS_NAME “$@”
fi  

Configure home/jenkins/jenkins-slave as the entry point of the Jenkins container

Jenkinsfile – Build & Publish Docker In Docker

The Jenkinsfile below shows how build and publish a  Docker image to Docker registry on a Dockerized Jenkins node:

//Running on Docker node

node(DOCKER_IMAGE){

deleteDir()

checkout([$class: ‘GitSCM’, branches: [[name: “${git_branch}”]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs:     [[credentialsId: ‘abc’, url: GIT_URL]]])

stage(‘docker build, tag & push’){

//credentials for Docker registry

withCredentials([usernamePassword(credentialsId: ‘dockerpush’, passwordVariable: ‘pass’, usernameVariable: ‘user’)]) {

dir(“${dockerfile_path}”)
{

//Build the Docker image
def dockerImage=docker.build(“${docker_source_image_tag}”)

//Tag the image

sh ‘docker tag “${docker_source_image_tag}” “${docker_target_image_tag}”‘

docker.withRegistry(‘https://docker-test.com’, ‘dockerpush’) {

//Log into the Docker registry

sh “docker login -u ${user} -p ${pass} https://docker-test.com”

//Push the image

dockerImage.push(‘latest’)
}

}

}
}

}

Jenkins – Making Data Persistent In Docker Slave

As in Jenkins Docker Slave, every time a job runs, a new Docker container is started and terminated upon job completion. This will mean it will download all the dependencies every time. To avoid this, we will use the Volume function in Docker.

As we are using the Docker Plugin, there is a field to do this – Volumes.

Docker Jenkins plugin

 

In the example above, we map path /var/lib/jenkins/tools on the Slave machine to path /home/jenkins/tools in Docker container, and /home/jenkins/.m2 on Slave machine to /home/jenkins/.m2 on Docker container. We can specify the mode of Read/Write, Read-Only, etc, by default is Read/Write.

Therefore, all Jenkins tools and Maven dependencies will be stored on the host or Slave Machine every time Docker container runs and will not need to be downloaded upon next Docker container starts. So build time will be saved.

 

How To Set Up Jenkins 2.0 Master & Slaves On Docker

Jenkins 2.0 Master In Docker

We can just use the Jenkins Docker official image, or you can just install Jenkins 2.0 normally.

 Jenkins Slave In Docker

Setup

  • Install Docker
  • Open up TCP port by adding the following in /etc/default/docker
    DOCKER_OPTS="-H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock"
  • On Jenkins Master, install Docker Plugin on Master->Manage Jenkins->Manage Plugins
  • On Master->Manage Jenkins->Cloud configure the communication with Jenkins slave node
  • Docker URL is the IP of the Slave machine in TCP
  • Click on Test Connection, if successful will show the Docker version and Docker API versionDocker Plugin

 

  • Have Docker Jenkins Slave images in the slave box
  • On Master->Manage Jenkins->Manage Plugins->Cloud->Add Docker Template
  • The SSH credentials to access the Docker Jenkins Slave container is the Jenkins user setup in Dockerfile and Jenkins MasterScreen Shot 2017-03-27 at 4.29.05 PM
Docker Slave Image

There are some Docker images that you can use like Docker Slave image , or you can write your own Dockerfile.

Docker image contains a minimum of:

  • Ubuntu
  • Java
  • Jenkins user and password
  • Git
  • OpenSSH for Jenkins Master to SSH to Slave machine
  • Maven, Ruby, etc depends on what your project needs
  • Version managers like NPM or RVM cannot be installed in Docker due to we cannot “source” files like .bashrc

It is a sshd service running on port 22, therefore in the Dockerfile, you will need:

EXPOSE 22

CMD [“/usr/sbin/sshd”, “-D”]

Running
  • We restrict Jenkins jobs to run based on the label we give in Docker template
  • When job runs, Jenkins Master will spin up the Docker image on the Slave machine
  • When job completes, the Docker image will be terminated
  • Therefore, we can have multiple Docker images for different types of jobs, Ruby, Maven, NodeJS on a single Slave machine

Docker – Using Tiller To Overwrite Environment Specific Variables

To use Tiller, in Dockerfile, we specify:

ADD deploy/tiller/*.yaml /etc/tiller/
ADD deploy/tiller/environments/dev /etc/tiller/environments/
ADD deploy/tiller/templates/* /etc/tiller/templates/

Tiller folder comprises of the following:

  • environments

This is where the yaml for environment specific variables are written:

#These are the variables to overwrite service.conf.erb template

service.conf.erb:
target: /etc/appleapi/application.ini
config:
environment_name: “prod”

#These are the variables to overwrite template.conf.erb template

template.conf.erb:
target: /etc/appleapi/application.conf

#database
appleapi_database_url: jdbc:postgresql://appledb:5432/appleapi
deliveryapi_database_user: apple
deliveryapi_database_password: apple

  • templates

There are the files in the server to be overwritten:

# PostgreSQL configuration (default datasource)
db.default.driver=org.postgresql.Driver
db.default.url=”<%=appleapi_database_url%>”
db.default.username=”<%=appleapi_database_user%>”
db.default.password=”<%=appleapi_database_password%>”

  • common.yaml

data_sources: [ “defaults” , “file” , “environment” ]
template_sources: [ file ]
deep_merge: true

Load the defaults, file and then environment data source to overwrite the templates

  • default.yaml

global:
application_name: “appleapi”
application_port: 9001

Default variables that are shared regardless of environment

Run it in Dockerfile:

RUN tiller -b /etc/tiller -n -v -e production

Docker – How To Run A Debian Package In Docker

Below are the major steps on how to run a Debian package in Docker

Dockerfile
  • Download your Debian file

# Download .deb fileRUN wget $debian_url \
&& sudo dpkg -i appleapi.deb \
&& apt-get install -f

  • Using Ruby Tiller to overwrite environment specific configs (optional)

#Tiller
RUN sudo apt-get update && sudo apt-get -y install ruby
RUN gem install tiller

ADD deploy/tiller/*.yaml /etc/tiller/
ADD deploy/tiller/environments/dev /etc/tiller/environments/
ADD deploy/tiller/templates/* /etc/tiller/templates/

  • Run Tiller and tell it to use development environment configuration

RUN tiller -b /etc/tiller -n -v -e development

  • Expose the port of your app

EXPOSE 9001

  • Start your app via Supervisord (optional as you could just use CMD)

CMD [“/usr/bin/supervisord”]

  • Build the Docker file

docker build  -t appleapi .

  • Run Docker in localhost

docker run -p 9001:9001 appleapi

supervisord.conf

[supervisord]
nodaemon=true

[program:appleapi]
startsecs = 0
autorestart = false
command=/bin/bash -c “appleapi/bin/appleapi”

© 2021 Chuan Chuan Law

Theme by Anders NorenUp ↑