Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@
# own secret vars store.
personal.auto.tfvars

# в этом файле ничег осекретного, поэтому добавляю в гит без опасений
#terraform.tfvars

terraform.tfvars
# а вот тут секретики, поэтому не показываю
personal.auto.tfvars

tfplan

tfplan
# тут ключ от квартиры, где деньги лежат
yc-terraform-training-acc-key.json
184 changes: 134 additions & 50 deletions 01/hw-01.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,79 +9,163 @@

### Чек-лист готовности к домашнему заданию

1. Скачайте и установите **Terraform** версии >=1.8.4 . Приложите скриншот вывода команды ```terraform --version```.
2. Скачайте на свой ПК этот git-репозиторий. Исходный код для выполнения задания расположен в директории **01/src**.
3. Убедитесь, что в вашей ОС установлен docker.
<img width="1036" height="334" alt="image" src="https://github.com/user-attachments/assets/930d4ea7-7521-41cb-881f-43ae37ae09f1" />

------

### Инструменты и дополнительные материалы, которые пригодятся для выполнения задания

1. Репозиторий с ссылкой на зеркало для установки и настройки Terraform: [ссылка](https://github.com/netology-code/devops-materials).
2. Установка docker: [ссылка](https://docs.docker.com/engine/install/ubuntu/).
------
### Внимание!! Обязательно предоставляем на проверку получившийся код в виде ссылки на ваш github-репозиторий!
------

### Задание 1

1. Перейдите в каталог [**src**](https://github.com/netology-code/ter-homeworks/tree/main/01/src). Скачайте все необходимые зависимости, использованные в проекте.
2. Изучите файл **.gitignore**. В каком terraform-файле, согласно этому .gitignore, допустимо сохранить личную, секретную информацию?(логины,пароли,ключи,токены итд)
3. Выполните код проекта. Найдите в state-файле секретное содержимое созданного ресурса **random_password**, пришлите в качестве ответа конкретный ключ и его значение.
4. Раскомментируйте блок кода, примерно расположенный на строчках 29–42 файла **main.tf**.
Выполните команду ```terraform validate```. Объясните, в чём заключаются намеренно допущенные ошибки. Исправьте их.
5. Выполните код. В качестве ответа приложите: исправленный фрагмент кода и вывод команды ```docker ps```.
6. Замените имя docker-контейнера в блоке кода на ```hello_world```. Не перепутайте имя контейнера и имя образа. Мы всё ещё продолжаем использовать name = "nginx:latest". Выполните команду ```terraform apply -auto-approve```.
Объясните своими словами, в чём может быть опасность применения ключа ```-auto-approve```. Догадайтесь или нагуглите зачем может пригодиться данный ключ? В качестве ответа дополнительно приложите вывод команды ```docker ps```.
8. Уничтожьте созданные ресурсы с помощью **terraform**. Убедитесь, что все ресурсы удалены. Приложите содержимое файла **terraform.tfstate**.
9. Объясните, почему при этом не был удалён docker-образ **nginx:latest**. Ответ **ОБЯЗАТЕЛЬНО НАЙДИТЕ В ПРЕДОСТАВЛЕННОМ КОДЕ**, а затем **ОБЯЗАТЕЛЬНО ПОДКРЕПИТЕ** строчкой из документации [**terraform провайдера docker**](https://docs.comcloud.xyz/providers/kreuzwerker/docker/latest/docs). (ищите в классификаторе resource docker_image )
1. Терраформ инициализирован, зависимости скачаны

<img width="1928" height="1169" alt="image" src="https://github.com/user-attachments/assets/a615d906-a466-4333-a1a5-e83a4acf80c4" />

2. Личную секретную информациюдопустимо хранить в `personal.auto.tfvars`, т.к. он игнорируется и не попадает в репозиторий. И более того, он даже подписан комментарием `# own secret vars store.`

3. Безуспешные попытки получить пароль средствами Терраформа:
<img width="1931" height="581" alt="image" src="https://github.com/user-attachments/assets/7862e499-88a3-4651-ad28-588cd148b73d" />

При этом пароь в явном виде есть в файле `terraform.tfstate`

<img width="1931" height="923" alt="image" src="https://github.com/user-attachments/assets/b521ac5d-5018-4f90-b190-c35484478c50" />


**Пароль: AgA2Q1IDjYamAdzh**


4. Ошибка 1: Missing name for resource

<img width="1359" height="211" alt="image" src="https://github.com/user-attachments/assets/523ca376-478f-42d2-b889-3628f5389285" />

Суть ошибки - в Terraform каждый ресурс должен иметь два лейбла (type, name), а в файле только "docker_image".

Ошибка 2: Invalid resource name

<img width="1383" height="205" alt="image" src="https://github.com/user-attachments/assets/9be5d64c-2c4a-4456-88c5-27ffb3a5f999" />

Суть ошибки: Имя ресурса не может начинаться с цифры (1nginx). Имя должно начинаться с буквы или подчёркивания. Разрешены только буквы, цифры, подчёркивание и дефис.

Ошибка 3: Reference to undeclared resource

<img width="1383" height="207" alt="image" src="https://github.com/user-attachments/assets/26ee3459-2fc8-4b27-94ba-0d682037c51f" />

Суть ошибки: задано имя ресурса `random_password.random_string_FAKE`, которого нет в конфигурации (нужно убрать `_FAKE`), нужно исправить последнюю букву в слове `resulT` на строчную.
Исправление:
```
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0.1"
}
}
required_version = ">=1.8.4" /*Многострочный комментарий.
Требуемая версия terraform */
}
provider "docker" {}

#однострочный комментарий

resource "random_password" "random_string" {
length = 16
special = false
min_upper = 1
min_lower = 1
min_numeric = 1
}


resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = true
}


resource "docker_container" "nginx1" {
image = docker_image.nginx.image_id
name = "example_${random_password.random_string.result}"

ports {
internal = 80
external = 9090
}
}
```

5. Исправленный main.tf выше.
Вывод команды `docker ps`:

<img width="1707" height="89" alt="image" src="https://github.com/user-attachments/assets/124878e3-68a2-49a0-a694-fbccfc92b034" />


6. Опасность применения ключа `-auto-approve` в том, что он позволяет применить все изменения без подтверждения. Т.е. есть явный риск случайно удалить или изменить важные ресурсы без предварительной проверки.
Польза - для автоматизации, когда код заведомо работает и подтверждения не требуется, либо для тестовой среды, где нет риска удалить что-то важное.

Новый вывод команды ```docker ps```.

<img width="1617" height="87" alt="image" src="https://github.com/user-attachments/assets/c3b4792b-6d84-4459-9860-8adb8bfd4a96" />


7. Ресурсы уничтожены:

<img width="1922" height="424" alt="image" src="https://github.com/user-attachments/assets/79b599db-77f5-4823-ab1a-a3734d9177e3" />

Содержимое файла **terraform.tfstate**:

<img width="1538" height="276" alt="image" src="https://github.com/user-attachments/assets/c6583369-28b3-4501-83b0-7aa9b5a2c64c" />

8. При уничтожении ресурсов с помощью команды `terraform destroy` Docker-образ `nginx:latest` не был удалён и остался на сервере, потому что в коде нет указания его удалить. В Terraform-провайдере Docker для ресурса docker_image это управляется параметром `keep_locally`. Если `keep_locally = false`, образ будет удалён; если keep_locally = true или параметр не задан, образ останется на сервере.


------

## Дополнительное задание (со звёздочкой*)

**Настоятельно рекомендуем выполнять все задания со звёздочкой.** Они помогут глубже разобраться в материале.
Задания со звёздочкой дополнительные, не обязательные к выполнению и никак не повлияют на получение вами зачёта по этому домашнему заданию.

### Задание 2*

1. Создайте в облаке ВМ. Сделайте это через web-консоль, чтобы не слить по незнанию токен от облака в github(это тема следующей лекции). Если хотите - попробуйте сделать это через terraform, прочитав документацию yandex cloud. Используйте файл ```personal.auto.tfvars``` и гитигнор или иной, безопасный способ передачи токена!
2. Подключитесь к ВМ по ssh и установите стек docker.
3. Найдите в документации docker provider способ настроить подключение terraform на вашей рабочей станции к remote docker context вашей ВМ через ssh.
4. Используя terraform и remote docker context, скачайте и запустите на вашей ВМ контейнер ```mysql:8``` на порту ```127.0.0.1:3306```, передайте ENV-переменные. Сгенерируйте разные пароли через random_password и передайте их в контейнер, используя интерполяцию из примера с nginx.(```name = "example_${random_password.random_string.result}"``` , двойные кавычки и фигурные скобки обязательны!)
(Не нашёл в доке kreuzwerker/docker способа поднять контейнер именно на 127.0.0.1)

`main.tf` получился такой:
https://github.com/wiqt8r/terraform-homeworks/blob/main/01/src/main.tf

Наличие секретных env-переменных в контейнере:

<img width="1807" height="609" alt="image" src="https://github.com/user-attachments/assets/618d825a-a815-4e0d-8d67-3605d2809c7f" />


### Задание 3*
1. Tofu установлен:

<img width="661" height="98" alt="image" src="https://github.com/user-attachments/assets/213207b2-07d7-4653-a9c2-50468ff4869b" />

2. Получить провайдеры из registry.opentofu.org не вышло - видимо, санкции.
```
environment:
- "MYSQL_ROOT_PASSWORD=${...}"
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- "MYSQL_PASSWORD=${...}"
- MYSQL_ROOT_HOST="%"
Could not resolve provider kreuzwerker/docker: could not connect to registry.opentofu.org: failed to request discovery document: 403 Forbidden
```
Скачал их с гитхаба.

6. Зайдите на вашу ВМ , подключитесь к контейнеру и проверьте наличие секретных env-переменных с помощью команды ```env```. Запишите ваш финальный код в репозиторий.
<img width="866" height="184" alt="image" src="https://github.com/user-attachments/assets/3d902af1-9ff7-47c5-be7d-8b5edfce8c50" />

### Задание 3*
1. Установите [opentofu](https://opentofu.org/)(fork terraform с лицензией Mozilla Public License, version 2.0) любой версии
2. Попробуйте выполнить тот же код с помощью ```tofu apply```, а не terraform apply.
------
Пришлось повозиться с `~/.tofurc` и прописать явный путь к провайдерам.
```
provider_installation {
filesystem_mirror {
path = "/home/wiqtor/.opentofu/plugins"
include = ["registry.opentofu.org/hashicorp/random", "registry.opentofu.org/kreuzwerker/docker"]
}
}
```

### Правила приёма работы
Установил локально

Домашняя работа оформляется в отдельном GitHub-репозитории в файле README.md.
Выполненное домашнее задание пришлите ссылкой на .md-файл в вашем репозитории.
<img width="1933" height="1232" alt="image" src="https://github.com/user-attachments/assets/bf4f48a2-3c0a-4a99-837d-32b2844d8b64" />

### Критерии оценки
Развернул:

Зачёт ставится, если:
<img width="1529" height="489" alt="image" src="https://github.com/user-attachments/assets/cefe6008-03a5-495f-9f71-044c225a8af3" />

* выполнены все задания,
* ответы даны в развёрнутой форме,
* приложены соответствующие скриншоты и файлы проекта,
* в выполненных заданиях нет противоречий и нарушения логики.
Работает:

На доработку работу отправят, если:
<img width="1815" height="148" alt="image" src="https://github.com/user-attachments/assets/3148b4af-c2a6-44b8-bb15-75e294007f1d" />

* задание выполнено частично или не выполнено вообще,
* в логике выполнения заданий есть противоречия и существенные недостатки.

6 changes: 3 additions & 3 deletions 01/src/.terraformrc
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
provider_installation {
network_mirror {
url = "https://terraform-mirror.yandexcloud.net/"
include = ["registry.terraform.io/*/*"]
url = "https://registry.comcloud.xyz/"
}
direct {
exclude = ["registry.terraform.io/*/*"]
}
}
}

52 changes: 31 additions & 21 deletions 01/src/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,47 @@ terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0.1"
version = "~> 3.8.0"
}
}
required_version = ">=1.8.4" /*Многострочный комментарий.
Требуемая версия terraform */
required_version = ">=1.8.4"
}
provider "docker" {}

#однострочный комментарий
provider "docker" {
host = "ssh://wqtr@89.169.167.232:22"
}

resource "random_password" "random_string" {
length = 16
special = false
min_upper = 1
min_lower = 1
min_numeric = 1
resource "random_password" "mysql_root" {
length = 16
upper = true
lower = true
numeric = true
special = false
}

/*
resource "docker_image" {
name = "nginx:latest"
keep_locally = true
resource "random_password" "mysql_user" {
length = 16
upper = true
lower = true
numeric = true
special = false
}

resource "docker_container" "1nginx" {
image = docker_image.nginx.image_id
name = "example_${random_password.random_string_FAKE.resulT}"
resource "docker_container" "mysql" {
image = "mysql:8"
name = "example_${random_password.mysql_root.result}"

ports {
internal = 80
external = 9090
internal = 3306
external = 3306
}

env = [
"MYSQL_ROOT_PASSWORD=${random_password.mysql_root.result}",
"MYSQL_DATABASE=wordpress",
"MYSQL_USER=wordpress",
"MYSQL_PASSWORD=${random_password.mysql_user.result}",
"MYSQL_ROOT_HOST=%"
]
}
*/

Loading