Жадаў бы распавесці пра новы CLI tool які я напісаў для рашэння адной старой праблемы.
праблема
Terraform ужо даўно стаў стандартам у Devops/Cloud/IT супольнасці. Рэч вельмі зручная і карысная, каб займацца infrastructure as code. Ёсць шмат любат у Terraform і шмат відэльцаў, вострых нажоў і грабляў.
З Terraform вельмі зручна рабіць новыя рэчы і потым імі кіраваць, мяняць ці выдаляць. А што рабіць тым у каго ёсць вялізная інфраструктура ў воблаку і не створана праз Terraform? Перапісваць і пераствараць усё воблака як то дорага і небяспечна.
Я сутыкаўся з такой праблемай на 2 працах, самы просты прыклад калі хочаш што ўсё было ў гіце выглядзе тэраформаў файлаў, а ў цябе 250+ бакетаў і пісаць іх у для тэраформа рукамі як тое шмат.
Ёсць
Наогул усё як на малюнку толькі з права на лева
Папярэджанні: Аўтар пол жыцця жыве не ў Расіі і піша на рускай мала. Асцярожна памылкі ў арфаграфіі.
Рашэнні
1. Ёсць гатовае і старое рашэнні для AWS
Як працуе terraforming ён бярэ з SDK AWS дадзеныя і генеруе tf і tfstate праз темплет.
Тут 3 праблемы:
1. Заўсёды там будзе адставання ў абнаўленнях
2. tf файлы часам выходзяць бітыя
3. tfstate збіраецца асобна ад tf і не заўсёды збягаецца
Наогул складана атрымае вынік пры якім `terraform plan` скажа што не змен
2. `terraform import` - убудаваная каманда ў terraform. Як працуе?
Пішаш пусты TF файл з імем і выглядам рэсурсу, потым запускаеш `terraform import` і перадаеш ID рэсурсу. terraform звяртаецца да правайдэра атрымлівае дадзеныя і робіць tfstate файл.
Тут 3 праблемы:
1. Атрымліваем толькі tfstate файл а tf пусты трэба рукамі пісаць ці канвертаваць з tfstate
2. Умее працаваць толькі з адным рэсурсаў кожны раз і не падтрымлівае ўсе рэсурсы. І што мне зноў рабіць з 250+ бакетамі
3. Трэба ведаць ID рэсурсаў - гэта значыць трэба абмотваць яго гэта ў код які дастае спіс рэсурсаў
Наогул вынік частковы і не маштабуецца добра
Маё рашэнні
патрабаванні:
1. Магчымасць стварыць файлы tf і tfstate па рэсурсах. Напрыклад спампаваць усе бакеты/security group/load balancer і што `terraform plan` вяртаў што няма змен
2. Трэба 2 аблокі GCP + AWS
3. Глабальнае рашэнне якое лёгка абнаўляць кожны раз і не марнаваць час на кожны рэсурс па 3 дні працы
4. Зрабіць Open source – праблема ва ўсіх такая
Мова Go - таму я люблю, і на ім ёсць бібліятэка для стварэння HCL файлаў якая выкарыстоўваецца ў terraform + шмат кода ў terraform які можа быць карысны
Шлях
Спроба першая
Пачаў просты варыянт. Звароты ў воблака праз SDK за патрэбным рэсурсам і канвертавання яго ў палі для terraform. Спроба памерла адразу на security group, таму што мне не спадабалася 1.5 дня канвертаваць толькі security group(а рэсурсаў шмат). Доўга і потым палі могуць мяняць/дададуцца
Спроба другая
Заснавана на ідэі апісанай
Зараз зоймемся рэкурсіўнай парнаграфіяй напісанне канвертара для tfstate у tf. Для тых, хто ніколі не чытаў tfstate то гэта JSON, але асаблівы.
Вось яго важная частка attributes
"attributes": {
"id": "default/backend-logging-load-deployment",
"metadata.#": "1",
"metadata.0.annotations.%": "0",
"metadata.0.generate_name": "",
"metadata.0.generation": "24",
"metadata.0.labels.%": "1",
"metadata.0.labels.app": "backend-logging",
"metadata.0.name": "backend-logging-load-deployment",
"metadata.0.namespace": "default",
"metadata.0.resource_version": "109317427",
"metadata.0.self_link": "/apis/apps/v1/namespaces/default/deployments/backend-logging-load-deployment",
"metadata.0.uid": "300ecda1-4138-11e9-9d5d-42010a8400b5",
"spec.#": "1",
"spec.0.min_ready_seconds": "0",
"spec.0.paused": "false",
"spec.0.progress_deadline_seconds": "600",
"spec.0.replicas": "1",
"spec.0.revision_history_limit": "10",
"spec.0.selector.#": "1",
Тут ёсць:
1. id - string
2. metadata - array памерам 1 і ў ім аб'ект з палямі які апісаны ніжэй
3. spec - hash памерам 1 і ў ім key, value
Карацей вясёлы фармат, усё можа быць у глыб таксама на некалькі ўзроўняў
"spec.#": "1",
"spec.0.min_ready_seconds": "0",
"spec.0.paused": "false",
"spec.0.progress_deadline_seconds": "600",
"spec.0.replicas": "1",
"spec.0.revision_history_limit": "10",
"spec.0.selector.#": "1",
"spec.0.selector.0.match_expressions.#": "0",
"spec.0.selector.0.match_labels.%": "1",
"spec.0.selector.0.match_labels.app": "backend-logging-load",
"spec.0.strategy.#": "0",
"spec.0.template.#": "1",
"spec.0.template.0.metadata.#": "1",
"spec.0.template.0.metadata.0.annotations.%": "0",
"spec.0.template.0.metadata.0.generate_name": "",
"spec.0.template.0.metadata.0.generation": "0",
"spec.0.template.0.metadata.0.labels.%": "1",
"spec.0.template.0.metadata.0.labels.app": "backend-logging-load",
"spec.0.template.0.metadata.0.name": "",
"spec.0.template.0.metadata.0.namespace": "",
"spec.0.template.0.metadata.0.resource_version": "",
"spec.0.template.0.metadata.0.self_link": "",
"spec.0.template.0.metadata.0.uid": "",
"spec.0.template.0.spec.#": "1",
"spec.0.template.0.spec.0.active_deadline_seconds": "0",
"spec.0.template.0.spec.0.container.#": "1",
"spec.0.template.0.spec.0.container.0.args.#": "3",
Зрэшты хто жадае задачу на праграмавання для сумоўя то проста папытаеце напісаць парсер на гэтую справу 🙂
Пасля доўгіх спроб напісаць парсер без багаў я знайшоў частку яго ў кодзе terraform прычым самую важную частку. І ўсё быццам працавала норм
Спроба тры
terraform provider - гэта бінаркі у якіх ёсць код з усімі рэсурсамі і логікай для працы з API аблокаў. У кожнага аблокі ёсць свой provider і сам terraform толькі выклікае іх праз свой пратакол RPC паміж двума працэсамі.
Цяпер я вырашыў звяртацца напрамую да terraform providers праз RPC выклікі. Так выйшла хораша і дало магчымасць мяняць terraform providers на навейшыя і атрымліваць новыя магчымасць не змяняючы код. Яшчэ аказалася не ўсе палі ў tfstate павінны быць у tf, а як гэта даведацца? Толькі спытаць provider аб гэтым. Потым пачалася яшчэ адна рэкурсіўнай парнаграфіяй па зборцы рэгулярных выразаў важданін з пошукам палёў усярэдзіне tfstate на ўсіх узроўнях у глыб.
У канцы атрымалася карысны CLI tool у якога агульная інфраструктура для ўсіх terraform providers і можна лёгка дадаць новага. Таксама дадання рэсурсаў займае мала кода. Плюс усякія плюшкі тыпу злучэння паміж рэсурсамі. Вядома было шмат розных праблем якія ўсё не апісаць.
Назваў звярок Terrafomer.
фінал
Мы з дапамогай Terrafomer згенеравалі 500-700 тысяч радкоў кода tf + tfstate з двух аблоках. Змаглі ўзяць легасі рэчы і пачаць іх чапаць толькі праз terraform як у лепшых ідэях infrastructure as code. Проста магія калі бярэш велізарнае воблака і атрымліваеш праз каманду яго ў выглядзе terraform файлаў працоўных. А далей grep/replace/git і гэтак далей.
Вычасаў і прывёў у парадак, атрымаў дазволы. Выпусціў на гітхаб для ўсіх у чацвер(02.05.19).
Атрымаў ужо 600 зорак, 2 pull requests дадання падтрымкі openstack і kubernetes. Добрыя водгукі. Наогул праект карысны для людзей
Раю ўсім хто жадае пачаць працаваць з Terraform і не перапісваць усё для гэтага.
Буду рады pull requests, issues, stars.
дэма
Крыніца: habr.com