Jenkins – Kubernetes plugin: An example of building an image with a Maven project

 

An example of a pipeline for working with the plugin for kubernetis. We build the maven project, create a docker image with the received artifact and push it into the docker image storage.

 

Pipeline:

podTemplate(
  containers: [
    containerTemplate(
      name: 'maven',
      image: 'maven:latest',
      command: 'cat',
      ttyEnabled: true),
    containerTemplate(
      name: 'docker',
      image: 'docker:latest',
      command: 'cat',
      ttyEnabled: true,
      envVars: [
        secretEnvVar(key: 'DOCKER_LOGIN', secretName: 'docker-regestry-credentials', secretKey: 'username'),
        secretEnvVar(key: 'DOCKER_PASSWORD', secretName: 'docker-regestry-credentials', secretKey: 'password'),
        envVar(key: 'DOCKER_REGESTRY_URL', value: 'docker.artem.services'),
        envVar(key: 'DOCKER_REPO', value: 'artem')
      ]
    )
  ],
  volumes: [
    hostPathVolume(
      hostPath: '/var/run/docker.sock',
      mountPath: '/var/run/docker.sock')]
)
{
  node(POD_LABEL) {
    stage('Get a Maven project') {
      git 'https://git.artem.services/artem/maven-project.git'
      container('maven') {
        stage('Build a Maven project') {
          sh 'mvn -B clean install'
        }
      }
    }

    stage('Build Docker image') {
      container('docker') {
        writeFile file: "Dockerfile", text: """
            FROM tomcat:jdk8
            COPY ./web/target/*.war /usr/local/tomcat/webapps/
        """
        sh "docker build -t \$DOCKER_REGESTRY_URL/\$DOCKER_REPO/maven:${env.BUILD_ID} ."
        sh "docker login -u \$DOCKER_LOGIN -p \$DOCKER_PASSWORD \$DOCKER_REGESTRY_URL"
        sh "docker push \$DOCKER_REGESTRY_URL/\$DOCKER_REPO/maven:${env.BUILD_ID}"
      }
    }
  }
}

 

Dockerfile – already created in the pipeline itself.
envVar – taken from the secret of kubernetes

 Ansible Playbook – Install Docker on CentOS 7

The following example was taken as a Playbook.

This Playbook runs on the "docker" host group, installs the necessary packages for Docker, adds the Docker repository, installs Docker, launches it and adds it to autorun. Also adds the user "artem" to the group "docker"

 

docker.yaml

---
- name: Install Docker
  gather_facts: No
  hosts: docker

  tasks:
    - name: Install yum utils
      yum:
        name: yum-utils
        state: latest

    - name: Install device-mapper-persistent-data
      yum:
        name: device-mapper-persistent-data
        state: latest

    - name: Install lvm2
      yum:
        name: lvm2
        state: latest

    - name: Add Docker repo
      get_url:
        url: https://download.docker.com/linux/centos/docker-ce.repo
        dest: /etc/yum.repos.d/docker-ce.repo
      become: yes

    - name: Install Docker
      package:
        name: docker-ce
        state: latest
      become: yes

    - name: Start Docker service
      service:
        name: docker
        state: started
        enabled: yes
      become: yes

    - name: Add user artem to docker group
      user:
        name: artem
        groups: docker
        append: yes
      become: yes

 

Apply Playbook:

ansible-playbook docker.yaml

 Ansible – Install

A simple example of installing Ansible and adding a host.

Install Ansible:

 

RedHat systems:

yum install ansible

Deb systems:

apt install ansible

 

Generate an SSH key if it is not on the instance with Ansible:

ssh-keygen -t rsa

 

Add the public key to the host, which we will manage:

ssh-copy-id [email protected]

 

Add the host to the list:

vim /etc/ansible/hosts

 

And insert the following into it:

192.168.1.101 ansible_ssh_user=root

 

You can specify both an IP address and a DNS name.
root – the user on the remote machine that is used when connecting

 

Check the connection:

ansible -m ping all

192.168.1.101 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

 

all – run on all hosts specified in the file "/etc/ansible/hosts"

You can group hosts. For example, create a group "web" for our host:

 

[web]
192.168.1.101 ansible_ssh_user=root

 

Now you can call by group name:

ansible -m ping web

 Kubernetes – Save all manifest of an existing cluster

 

To save all manifests, create a BASH script:

vim k8s.sh

 

With the following contents:

#!/bin/bash

DIR='k8s-manifests/namespaces'

mkdir -p $DIR

for NAMESPACE in $(kubectl get -o=name namespaces | cut -d '/' -f2)
do
	for TYPE in $(kubectl get -n $NAMESPACE -o=name pvc,configmap,serviceaccount,secret,ingress,service,deployment,statefulset,hpa,job,cronjob)
	do
	    mkdir -p $(dirname $DIR/$NAMESPACE/$TYPE)
	    kubectl get -n $NAMESPACE -o=yaml $TYPE > $DIR/$NAMESPACE/$TYPE.yaml
	done
done

 

Add the execution bit and run it:

chmod +x k8s.sh
./k8s.sh

 

After executing in the current directory in the folder "k8s-manifests" will be saved all manifests ordered by namespaces and types.

 Terraform – Generate files based on existing infrastructure

To create Terraform files based on the existing infrastructure, we will use Terraformer

 

In this example, the macOS system will be used, so we install terraformer using homebrew:

brew install terraformer

 

Installation for other OSs can be found on the project page.

 

Create a directory for storing plugins (for working with providers)

mkdir -p ~/.terraform.d/plugins/darwin_amd64

 

 

Terraform file generation examples

AWS

We find the most current version of the darwin version, download, unzip and move the contents of the archive to the previously created directory
https://releases.hashicorp.com/terraform-provider-aws/

 

Create Terraform files for all S3 buckets and EC2 instances in the region: us-east-1

terraformer import aws --resources=s3,ec2_instance --regions=us-east-1

 

 

Kubernetes

 

kubectl must be installed and configured

 

We find the most current version of the darwin version, download, unzip and move the contents of the archive to the previously created directory

https://releases.hashicorp.com/terraform-provider-kubernetes/

 

Create Terraform files for all deployments, services and storageclasses

terraformer import kubernetes --resources=deployments,services,storageclasses

 

 

Lists of supported providers and resources can be found in more detail here.

 Docker Compose – WordPress

Example Docker Compose file for WordPress

docker-compose.yaml

version: '3.7'

services:
  artem_wp:
    container_name: artem_wp
    image: wordpress:php7.3
    volumes:
      - "/var/www/html/docker:/var/www/html"
    restart: always
    ports:
      - "80:80"
    links:
      - artem_db
    depends_on:
      - artem_db

  artem_db:
    container_name: artem_db
    image: mariadb:10
    restart: always
    volumes:
      - "artem_db_data:/var/lib/mysql"
    environment:
      MYSQL_ROOT_PASSWORD: 'your_root_password'
      MYSQL_DATABASE: 'your_db_name'
      MYSQL_USER: 'your_user_name'
      MYSQL_PASSWORD: 'your_user_password'

volumes:
  artem_db_data:

 Docker phpMyAdmin – Nginx reverse proxy

For a container with phpMyAdmin, you need to add a variable with an absolute path:

 

PMA_ABSOLUTE_URI: "https://artem.services/phpmyadmin"

 

The "location" block for Nginx (change the proxy path to yours):

    location  ~ \/phpmyadmin {
        rewrite ^/phpmyadmin(/.*)$ $1 break;
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_pass http://localhost:8080;
    }

 

Now phpMyAdmin will be available along the path:

https://artem.services/phpmyadmin/

 Docker – Multiple processes in one container

 

This example shows how to run 2 JAR files in one container.

As the base image we will use "phusion/baseimage"

First you need to create startup scripts, for convenience, in the example they will be called "start-first.sh" and "start-second.sh", in them we describe the launch of JAR files, for example

start-first.sh

#!/bin/bash
java -jar /usr/src/app/first.jar

 

start-second.sh

#!/bin/bash
java -jar /usr/src/app/second.jar

 

And create a Dockerfile

FROM phusion/baseimage:latest

CMD ["/sbin/my_init"]

RUN add-apt-repository ppa:openjdk-r/ppa && \
    apt-get update -q && \
    apt install -y openjdk-11-jdk

COPY ./my_application /usr/src/app

WORKDIR /usr/src/app

# Add first service
RUN mkdir /etc/service/first
ADD start-first.sh /etc/service/first/run
RUN chmod +x /etc/service/first/run

# Add second service
RUN mkdir /etc/service/second
ADD start-second.sh /etc/service/second/run
RUN chmod +x /etc/service/second/run

# Clean up
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*