INT 21h

Hi, I am Vladimir Smagin, SysAdmin and Kaptain. Telegram Email / GIT / Микроблог / Thingiverse / RSS / GPG

Прекрасный Hashicorp Packer

№ 11013 В разделе "Sysadmin" от May 30th, 2020,
В подшивках:

Допустим, у вас где-то в облачном сервисе хостится большое количество однотипных серверов, какая-то ферма из wordpress или кластер kubernetes и вы хотите сделать регулировку количества нод в зависимости от нагрузки для снижения стоимости эксплуатации. Нодами можно управлять руками или с помощью terraform и деплоить туда софт через ansible, но такой метод все равно плохо подходит когда это нужно делать быстро. Есть выход из ситуации в виде создания образа ноды из уже поднятой рабочей ноды, а потом в зависимости от нагрузки поднимать из этого образа новые ноды, но такой способ довольно затратен по времени и может легко вылиться в часы работы. Одна хитрая фирма, занимающаяся автоматизацией процессов создала штуку под названием Packer. И нет, это не накладной хуец, как мог бы подумать гугол.

Packer предназначен для быстрого создания образов для последующего развертывания. Конфигурационный файл описывает состояние будущей виртуальной машины и Packer старается привести образ к этому состоянию. Для примера можно взять Hetzner и какой-то php проект, для которого развернем nginx, php-fpm, модули баз данных, сами базы данных и пара административных утилит. Поскольку это всего-лишь пример работы, я здесь не упоминаю многих функций и рекомендую изучить полное руководство.

Все необходимые файлы лежат в этом git репозитории. Откройте hetzner.json и внимательно его изучите. В билдере как раз описывается требуемое состояние образа. Кстати, никто не запрещает иметь два билдера, или три, для прода, стейджинга или даже в другом облаке. В текущем примере билдер всего один для хецнера. Метки и имена очень полезны для последующей работы с образами, не пренебрегайте ими. Есть 2 пути доставки команд в образ, через user_data и через provisioners и между ними есть существенное отличие, которое рекомендую тщательно изучить, этот пример использует оба пути. Также провижионерами можно, например, копировать файлы или запустить ansible плейбук.

{
  "variables": {
    "hcloud_token": "my_hetzner_token"
  },
  "builders": [
    {
      "type": "hcloud",
      "token": "{{user `hcloud_token`}}",
      "image": "ubuntu-18.04",
      "location": "nbg1",
      "server_type": "cx11",
      "ssh_keys": [
        "vlad"
      ],
      "snapshot_name": "nginx-php",
      "snapshot_labels": {
        "test": "label",
        "shell": "bash",
        "python": "3"
      },
      "user_data_file": "ubuntu_deps.sh",
      "communicator": "ssh",
      "ssh_username": "root",
      "pause_before_connecting": "1m"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "script": "ubuntu_deps.sh"
    },
    {
      "type": "shell",
      "inline": [
        "sudo apt-get install -y php-mysql php-pgsql mysql-server postgresql-10"
      ]
    }
  ]
}

Для работы с апи хецнера требуется токен, который прописывается в виде переменной. Переменным значения можно не передавать, просто захардкодив их, или можно передать через переменные окружения. А можно брать вообще из Vault или Consul, в документации отлично рассказано про всё это. В моем примере я передаю их через командную строку при команде build, которая необходима для старта сборки образа. Такой подход позволяет лучше автоматизировать процесс сборки, т.к. json файл будет являться по сути шаблоном, в который ваша CI подставляет необходимые значения.

packer build -var 'hcloud_token=DF23J2LK35J23KJ2LK352GHJF2HGFD23HG' hetzner.json

После начала сборки в панели управления облаком вы увидите, что поднялась новая виртуальная машина заданного типа в которую устанавливаются все указанные пакеты. По окончании сборки с виртуальной машины снимется образ, который будет виден в разделе Snapshots. Теперь из этого образа можно поднимать огромное количество нод и их тип совсем не ограничен той, которая была прописана в server_type.

Я думаю вы с легкостью найдете применение этой замечательной утилите. Когда закончите изучение этой обратите внимание на другую крутую штуку Vagrant, которая помогает управлять виртуальными машинами.

Репозиторий с примером https://git.blindage.org/21h/packer-hetzner-sample

Нет комментариев »

Warm Image operator for Kubernetes

№ 11010 В разделе "Sysadmin" от May 28th, 2020,
В подшивках: , , ,

For example, you have huge image with your software and running POD on node. When POD moving to another node your image downloads to new node minute or two. This operator forces nodes to download image before rescheduling, so POD starts faster.

It runs /bin/sh with infinite loop on specified image as DaemonSet with additional options like NodeSelector, Affinity or resource limits. You can specify custom command if your image not contains /bin/sh interpreter or you want to run own script.

Your first warmer:

apiVersion: blindage.org/v1alpha1
kind: WarmImage
metadata:
  name: mongo4
spec:
  image: mongo
  version: "4"
  nodeSelector:
    node-role.kubernetes.io/master: ""

Now you warmed mongo:4 on all master nodes.

Repository here https://git.blindage.org/21h/warm-image-operator

Нет комментариев »

Простой способ подготовки библиотеки на golang к тестированию

№ 11006 В разделе "Programming" от May 26th, 2020,

Чтобы без проблем тестировать программы, написанные с использованием вашей библиотеки ее необходимо подготовить для этого. Делаем интерфейс, который будет использоваться в тестах, где ваши реальные функции будут заменены функциями с тестовыми данными.

package main

import "fmt"

// library 

type FooAdapter interface {
	Read() string
}

type Foo struct {
	mvar    string
}

func NewFoo(v string) FooAdapter {
	return &Foo{mvar:v}
}

func (a *Foo) Read() string {
	return "orig: " + a.mvar
}

// test 

func NewFooStub(v string) FooAdapter {
	return &FooStub{mvar: v}
}

type FooStub struct {
	mvar string
}

func (s *FooStub) Read() string {
	return "stub: " + s.mvar
}

func main() {
	z := NewFoo("o")
	fmt.Println("Read", z.Read())
	m := NewFooStub("s")
	fmt.Println("Read", m.Read())
}

https://play.golang.org/p/9utaWeDjNjo

Нет комментариев »

Hetzner DNS golang library

№ 10996 В разделе "Programming" от May 6th, 2020,

I made this library to interact with Hetzner DNS API in most easy way. Hopefully in future it will be used for Hetzner external-dns provider. Check out example directory and API_help.md.

Get your own token on Hetzner DNS and place it to token variable and run code

token := "jcB2UywP9XtZGhvhSHpH5m"
zone := "vhSHpH5mjcB2UywP9XtZGh"

log.Println("Create new instance")
hdns := hclouddns.New(token)

log.Println("Get zone", zone)

allRecords, err := hdns.GetRecords(zone)
if err != nil {
	log.Fatalln(err)
}

log.Println(allRecords.Records)
log.Println(allRecords.Error)

Нет комментариев »

Яндекс.Метрика

Fortune cookie: Today's spam: Will you bowl? Saturday-Sunday?