Jenkins — Kubernetes plugin: Пример сборки образа с Maven проектом

 

Пример пайплайна для работы с плагином для кубернетиса. Собираем maven проект, создаем докер образ с полученным артефактом и пушаем это в хранилище докер образов.

 

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 — создается уже в самом пайплане.
envVar — берутся из секрета кубернетиса

Linux/Unix — dd статус копирования

 

Для отображения статуса копирования при помощи утилиты "dd" используется ключ "status=progress", но в старой версии "dd" этого ключа еще нет, чтобы это обойти можно использовать утилиту "pv"

Пример:

sudo dd if=/Users/artem/Downloads/ubuntu.img | pv | sudo dd of=/dev/disk2 bs=32m

Ansible Playbook — Установка Docker в CentOS 7

За основу был взят следующий Playbook.

Данный Playbook запускается на группе хостов "docker", устанавливает необходимые пакеты для Docker'а, добавляет Docker репозиторий, устанавливает Docker, запускает его и добавляет в автозапуск. Так же добавляет пользователя "artem" в группу "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

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

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

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

 

Применяем Playbook:

ansible-playbook docker.yaml

Ansible — Установка

Простой пример установки Ansible и добавления хоста.

 

Устанавливаем Ansible:

RedHat системы:

yum install ansible

Deb системы:

apt install ansible

 

Генерируем SSH ключ, если его нет на инстансе с Ansible:

ssh-keygen -t rsa

 

Добавляем публичный ключ на хост, которым будем управлять:

ssh-copy-id [email protected]

 

Добавим хост в список:

vim /etc/ansible/hosts

 

И вставим туда следующее:

192.168.1.101 ansible_ssh_user=root

 

Вы можете указывать как IP адрес, так и DNS имя.
root — пользователь на удаленной машине, который используется при подключении

 

Проверим подключение:

ansible -m ping all

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

 

all — выполняем на всех хостах указанных в файле "/etc/ansible/hosts"

 

Можно группировать хосты. К примеру создадим группу "web" для нашего хоста:

[web]
192.168.1.101 ansible_ssh_user=root

 

Теперь можно вызывать по имени группы:

ansible -m ping web

Kubernetes — Сохраняем все манифесты существующего кластера

 

Для сохранения всех манифестов создайте BASH скрипт:

vim k8s.sh

 

Cо следующем содержимым:

#!/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

 

Добавьте бит исполнения и запустите его:

chmod +x k8s.sh
./k8s.sh

 

После выполнения в текущей директории в папке "k8s-manifests" будут сохранены все манифесты упорядоченные по неймспейсам и типам.

Terraform — Генерация файлов на основе существующей инфраструктуры

Для создания Terraform файлов на основе существующей инфраструктуры будем использовать Terraformer

 

В данном примере будет использоваться система macOS, так что terraformer устанавливаем с помощью homebrew:

brew install terraformer

 

Установку под другие ОС можно найти на странице проекта.

 

Создаем директорию под хранение плагинов (для работы с провайдерами)

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

 

 

Примеры генерации Terraform файлов

AWS

Находим самую актуальную версию darwin версию, скачиваем, распаковываем и перемещаем содержимое архива в созданную раннее директорию

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

 

Создадим Terraform файлы для всех S3 корзин и EC2 инстансов в регионе: us-east-1

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

 

 

Kubernetes

 

kubectl должен быть установлен и настроен

 

Находим самую актуальную версию darwin версию, скачиваем, распаковываем и перемещаем содержимое архива в созданную раннее директорию

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

 

Создадим Terraform файлы для всех deployments, services и storageclasses

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

 

 

Списки поддерживаемых провайдеров и ресурсов более детальнее можно посмотреть тут.

Docker Compose — WordPress

Пример Docker Compose файла для 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

Для контейнера с phpMyAdmin нужно добавить переменную с абсолютным путем:

 

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

 

Блок "location" для Nginx'а (поменяйте путь проксирования на свой):

    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;
    }

 

Теперь phpMyAdmin будет доступен по пути:

https://artem.services/phpmyadmin/

Docker — Несколько процессов в одном контейнере

 

В данном примере показан, как запустить 2 JAR файла в одном контейнере.

В качестве базового образа будем использовать "phusion/baseimage"

Для начала необходимо создать скрипты запуска, в для удобства в примере они будут называться "start-first.sh" и "start-second.sh", в них описываем запуск JAR файлов, к примеру

start-first.sh

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

 

start-second.sh

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

 

И создаем 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/*