Книга Облачная экосистема - читать онлайн бесплатно, автор Евгений Сергеевич Штольц. Cтраница 9
bannerbanner
Вы не авторизовались
Войти
Зарегистрироваться
Облачная экосистема
Облачная экосистема
Добавить В библиотекуАвторизуйтесь, чтобы добавить
Оценить:

Рейтинг: 0

Добавить отзывДобавить цитату

Облачная экосистема

– destroy

Terraform will perform the following actions:

– google_compute_instance.terraform

Plan: 0 to add, 0 to change, 1 to destroy.

Do you want to perform these actions?

Terraform will perform the actions described above.

Only 'yes' will be accepted to approve.

Enter a value: yes

google_compute_instance.terraform: Destroying… (ID: terraform)

google_compute_instance.terraform: Still destroying… (ID: terraform, 10s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 20s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 30s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 40s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 50s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 1m0s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 1m10s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 1m20s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 1m30s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 1m40s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 1m50s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 2m0s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 2m10s elapsed)

google_compute_instance.terraform: Still destroying… (ID: terraform, 2m20s elapsed)

google_compute_instance.terraform: Destruction complete after 2m30s

Apply complete! Resources: 0 added, 0 changed, 1 destroyed.

Создание инфраструктуры в AWS

Для создания конфигурации AWS кластера, создадим под него отдельную папку, а предыдущую – в параллельную:

esschtolts@cloudshell:~/terraform (agil7e-aleph-20391)$ mkdir gcp

esschtolts@cloudshell:~/terraform (agil7e-aleph-20391)$ mv main.tf gcp/main.tf

esschtolts@cloudshell:~/terraform (agil7e-aleph-20391)$ mkdir aws

esschtolts@cloudshell:~/terraform (agil7e-aleph-20391)$ cd aws

Role – аналог пользователя, только не для людей, а для сервисов, таких как AWS, а в нашем случае – это сервера EKS. Но мне видится аналогом ролей не пользователи, а группы, например, группа создания кластера, группа работы с БД и т.д. К серверу можно прикрепить только одну роль, при этом роль может содержать множество прав (Polices). В результате нам не нужно работать ни с логинами и паролями, ни с токенами, ни с сертификатами: хранить, передавать, ограничивать доступ, передавать – мы только указываем в WEB панели инструментов (IMA) или с помощью API (а производно в конфигурации) права. Нашему кластеру необходимы эти права, чтобы он смог само настраиваться и реплицироваться, так как он состоит из стандартных сервисов AWS. Для управления самими компонентами кластера AWS EC2 (сервера), AWS ELB (Elastic Load Balancer, балансировщик) и AWS KMS (Key Management Service, менеджер и шифрование ключей) нужен доступ AmazonEKSClusterPolicy, для мониторинга AmazonEKSServicePolicy с помощью компонентов CloudWatch Logs (мониторинг по логам), Route 53 (создание сети в зоне), IAM (управления правами). Я не стал описывать роль в конфиге и создал её через IAM по документации: https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role. html #create-service-role.

Для большей надёжности ноды Kubernetes кластера должны располагаться в разных зонах, то есть дата центрах. В каждом регионе, содержится несколько зон для поддержания отказоустойчивости, при этот сохраняя минимальных летенси (время ответа сервера) для местного населения. Важно заметить, что некоторые регионы могут быть представлены в нескольких экземплярах в рамках одной страны, например, US-east-1 в US East (N. Virginia) и US-east-2 в US East (Ohio) – обозначение регионов ведётся цифрами. Пока создание кластера EKS доступно только US-east зоне.

VPC для разработчика, простейшем варианте, сводится к наименованию подсети как конкретный ресурс.

Напишем конфигурацию в соответствии с документацией www.terraform.io/docs/providers/aws/r/eks_cluster. html :

esschtolts@cloudshell:~/terraform/aws (agile-aleph-203917)$ cat main.tf

provider "aws" {

access_key = "${var.token}"

secret_key = "${var.key}"

region = "us-east-1"

}


# Params


variable "token" {

default = ""

}

variable "key" {

default = ""

}


# EKS


resource "aws_eks_cluster" "example" {

enabled_cluster_log_types = ["api", "audit"]

name = "exapmle"

role_arn = "arn:aws:iam::177510963163:role/ServiceRoleForAmazonEKS2"


vpc_config {

subnet_ids = ["${aws_subnet.subnet_1.id}", "${aws_subnet.subnet_2.id}"]

}

}


output "endpoint" {

value = "${aws_eks_cluster.example.endpoint}"

}


output "kubeconfig-certificate-authority-data" {

value = "${aws_eks_cluster.example.certificate_authority.0.data}"

}


# Role


data "aws_iam_policy_document" "eks-role-policy" {

statement {

actions = ["sts:AssumeRole"]


principals {

type = "Service"

identifiers = ["eks.amazonaws.com"]

}

}

}


resource "aws_iam_role" "tf_role" {

name = "tf_role"

assume_role_policy = "${data.aws_iam_policy_document.eks-role-policy.json}"

tags = {

tag-key = "tag-value"

}

}


resource "aws_iam_role_policy_attachment" "attach-cluster" {

role = "tf_role"

policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"

}


resource "aws_iam_role_policy_attachment" "attach-service" {

role = "tf_role"

policy_arn = "arn:aws:iam::aws:policy/AmazonEKSServicePolicy"

}


# Subnet


resource "aws_subnet" "subnet_1" {

vpc_id = "${aws_vpc.main.id}"

cidr_block = "10.0.1.0/24"

availability_zone = "us-east-1a"


tags = {

Name = "Main"

}

}


resource "aws_subnet" "subnet_2" {

vpc_id = "${aws_vpc.main.id}"

cidr_block = "10.0.2.0/24"

availability_zone = "us-east-1b"


tags = {

Name = "Main"

}

}


resource "aws_vpc" "main" {

cidr_block = "10.0.0.0/16"

}

Через 9 минут 44 секунды я получил готовую самоподдерживающуюся инфраструктуру для кластера Kubernetes:

esschtolts@cloudshell:~/terraform/aws (agile-aleph-203917)$ ./../terraform apply -var="token=AKIAJ4SYCNH2XVSHNN3A" -var="key=huEWRslEluynCXBspsul3AkKlinAlR9+MoU1ViY7"

Теперь удалим (у меня заняло 10 минуты 23 секунды):

esschtolts@cloudshell:~/terraform/aws (agile-aleph-203917)$ ./../terraform destroy -var="token=AKIAJ4SYCNH2XVSHNN3A" -var="key=huEWRslEluynCXBspsul3AkKlinAlR9+MoU1ViY7"

Destroy complete! Resources: 7 destroyed.

Налаживание процесса CI/CD

Amazon предоставляет (aws.amazon.com/ru/devops/) большой спектр DevOps инструментов, оформленных в облачную инфраструктуру:

* AWS Code Pipeline – сервис позволяет создать из набора сервисов в визуальном редакторе цепочку этапов, через которые должен пройти код, прежде чем он попадёт на продакшн, например, сборку и тестирование.

* AWS Code Build – сервис предоставляет авто масштабирующую очередь сборки, что может потребоваться для компилируемых языков программирования, когда при добавлении фич или внесения изменений необходимо длительная пере компиляция всего приложения, при использовании одного сервера становится узким местом при выкатке изменений.

* AWS Code Deploy – автоматизирует развёртывание и возвращение к предыдущему состоянию продакшна в случаи ошибок.

* AWS CodeStar – сервис объединяет в себе основные возможности предыдущих сервисов.

Настраиваем удалённое управление

сервер артефактов

aws s3 ls s3://name_backet aws s3 sync s3://name_backet name_fonder –exclude *.tmp # в папку будет скачены файлы из бакета, например, сайт

Теперь, нам нужно скачать плагин работы с AWS:

esschtolts@cloudshell:~/terraform/aws (agile-aleph-203917)$ ./../terraform init | grep success

Terraform has been successfully initialized!

Теперь нам нужно получить доступы к AWS, для того кликаем по имени вашего пользователя шапки WEB-интерфейса, кроме My account, появится пункт My Security Credentials, выбрав который, переходим Access Key –> Create New Access Key. Создадим EKS (Elastic Kuberntes Service):

esschtolts@cloudshell:~/terraform/aws (agile-aleph-203917)$ ./../terraform apply

–var="token=AKIAJ4SYCNH2XVSHNN3A" -var="key=huEWRslEluynCXBspsul3AkKlinAlR9+MoU1ViY7"

Удаляем все:

$ ../terraform destroy

Создание кластера в GCP

node pool – объединение нод в кластер с

resource "google_container_cluster" "primary" {

name = "tf"

location = "us-central1"

$ cat main.tf # состояние конфигурации

terraform {

required_version = "> 0.10.0"

}

terraform {

backend "s3" {

bucket = "foo-terraform"

key = "bucket/terraform.tfstate"

region = "us-east-1"

encrypt = "true"

}

}

$ cat cloud.tf# конфигурации облака

provider "google" {

token = "${var.hcloud_token}"

}


$ cat variables.tf# переменные и получение токенов

variable "hcloud_token" {}


$ cat instances.tf# создание ресурсов

resource "hcloud_server" "server" { ....


$ terraform import aws_acm_certificate.cert arn:aws:acm:eu-central-1:123456789012:certificate/7e7a28d2-163f-4b8f-b9cd-822f96c08d6a

$ terraform init # Инициализация конфигов

$ terraform plan # Проверка действий

$ terraform apply # Запуск действий

Отладка:

essh@kubernetes-master:~/graylog$ sudo docker run –name graylog –link graylog_mongo:mongo –link graylog_elasticsearch:elasticsearch \

–p 9000:9000 -p 12201:12201 -p 1514:1514 \

–e GRAYLOG_HTTP_EXTERNAL_URI="http://127.0.0.1:9000/" \

–d graylog/graylog:3.0

0f21f39192440d9a8be96890f624c1d409883f2e350ead58a5c4ce0e91e54c9d

docker: Error response from daemon: driver failed programming external connectivity on endpoint graylog (714a6083b878e2737bd4d4577d1157504e261c03cb503b6394cb844466fb4781): Bind for 0.0.0.0:9000 failed: port is already allocated.

essh@kubernetes-master:~/graylog$ sudo netstat -nlp | grep 9000

tcp6 0 0 :::9000:::* LISTEN 2505/docker-proxy

essh@kubernetes-master:~/graylog$ docker rm graylog

graylog

essh@kubernetes-master:~/graylog$ sudo docker run –name graylog –link graylog_mongo:mongo –link graylog_elasticsearch:elasticsearch \

–p 9001:9000 -p 12201:12201 -p 1514:1514 \

–e GRAYLOG_HTTP_EXTERNAL_URI="http://127.0.0.1:9001/" \

–d graylog/graylog:3.0

e5aefd6d630a935887f494550513d46e54947f897e4a64b0703d8f7094562875

https://blog.maddevs.io/terrafom-hetzner-a2f22534514b

Для примера, создадим один инстанс:

$ cat aws/provider.tf

provider "aws" {

region = "us-west-1"

}

resource "aws_instance" "my_ec2" {

ami = "${data.aws_ami.ubuntu.id}"

instance_type = "t2.micro"

}


$ cd aws

$ aws configure

$ terraform init

$ terraform apply –auto-approve

$ cd ..

provider "aws" {

region = "us-west-1"

}

resource "aws_sqs_queue" "terraform_queue" {

name = "terraform-queue"

delay_seconds = 90

max_message_size = 2048

message_retention_seconds = 86400

receive_wait_time_seconds = 10

}

data "aws_route53_zone" "vuejs_phalcon" {

name = "test.com."

private_zone = true

}

resource "aws_route53_record" "www" {

zone_id = "${data.aws_route53_zone.vuejs_phalcon.zone_id}"

name = "www.${data.aws_route53_zone.selected.name}"

type = "A"

ttl = "300"

records = ["10.0.0.1"]

}

resource "aws_elasticsearch_domain" "example" {

domain_name = "example"

elasticsearch_version = "1.5"

cluster_config {

instance_type = "r4.large.elasticsearch"

}

snapshot_options {

automated_snapshot_start_hour = 23

}

}

resource "aws_eks_cluster" "eks_vuejs_phalcon" {

name = "eks_vuejs_phalcon"

role_arn = "${aws_iam_role.eks_vuejs_phalcon.arn}"


vpc_config {

subnet_ids = ["${aws_subnet.eks_vuejs_phalcon.id}", "${aws_subnet.example2.id}"]

}

}

output "endpoint" {

value = "${aws_eks_cluster.eks_vuejs_phalcon.endpoint}"

}

output "kubeconfig-certificate-authority-data" {

value = "${aws_eks_cluster.eks_vuejs_phalcon.certificate_authority.0.data}"

}

provider "google" {

credentials = "${file("account.json")}"

project = "my-project-id"

region = "us-central1"

}

resource "google_container_cluster" "primary" {

name = "my-gke-cluster"

location = "us-central1"

remove_default_node_pool = true

initial_node_count = 1

master_auth {

username = ""

password = ""

}

}

output "client_certificate" {

value = "${google_container_cluster.primary.master_auth.0.client_certificate}"

}

output "client_key" {

value = "${google_container_cluster.primary.master_auth.0.client_key}"

}

output "cluster_ca_certificate" {

value = "${google_container_cluster.primary.master_auth.0.cluster_ca_certificate}"

}

$ cat deployment.yml

apiVersion: apps/v1

kind: Deployment

metadata:

name: phalcon_vuejs

namespace: development

spec:

selector:

matchLabels:

app: vuejs

replicas: 1

template:

metadata:

labels:

app: vuejs

spec:

initContainers:

– name: vuejs_build

image: vuejs/ci

volumeMounts:

– name: app

mountPath: /app/public

command:

– /bin/bash

– -c

– |

cd /app/public

git clone essch/vuejs_phalcon:1.0 .

npm test

npm build

containers:

– name: healtcheck

image: mileschou/phalcon:7.2-cli

args:

– /bin/sh

– -c

– cd /usr/src/app && git clone essch/app_phalcon:1.0 && touch /tmp/healthy && sleep 10 && php script.php

readinessProbe:

exec:

command:

– cat

– /tmp/healthy

initialDelaySeconds: 5

periodSeconds: 5

livenessProbe:

exec:

command:

– cat

– /tmp/healthy

initialDelaySeconds: 15

periodSeconds: 5

voumes:

– name: app

emptyDir: {}

Вот и мы создали AWS EC2 инстанс. Мы опустили указание ключей, так как AWS API уже авторизован и эта авторизация будет использоваться Terraform.

Также, для использования кода, Terraform поддерживает переменные, данные и модули.

Создадим отдельную сеть:

resource "aws_vpc" "my_vpc" {

cidr_block = "190.160.0.0/16"

instance_target = "default"

}

resource "aws_subnet" "my_subnet" {

vpc_id = "${aws_vpc.my_vpc.id}"

cidr_block = "190.160.1.0/24"

}

$ cat gce/provider.tf

provider "google" {

credentials = "${file("account.json")}"

project = "my-project-id"

region = "us-central1"

}

resource "google_compute_instance" "default" {

name = "test"

machine_type = "n1-standard-1"

zone = "us-central1-a"

}

$ cd gce

$ terraform init

$ terraform apply

$ cd ..

Для распределенной работы поместим состояние в AWS S3 состояние инфраструктуры (так же можно помещать другие данные), но для безопасности в другой регион:

terraform {

backend "s3" {

bucket = "tfstate"

key = "terraform.tfstate"

region = "us-state-2"

}

}

provider "kubernetes" {

host = "https://104.196.242.174"

username = "ClusterMaster"

password = "MindTheGap"

}


resource "kubernetes_pod" "my_pod" {

spec {

container {

image = "Nginx:1.7.9"

name = "Nginx"

port {

container_port = 80

}

}

}

}

Команды:

terraform init # скачивание зависимостей в соответствии с конфигами, проверка их

terraform validate # проверка синтаксиса

terraform plan # детально посмотреть, как будет изменена инфраструктура и почему именно так, например,

будет ли изменена только мета информация у сервиса или будет пересоздан сам сервис, что часто недопустимо для баз данных.

terraform apply # применение изменений

Общая часть для всех провайдеров – ядро.

$ which aws

$ aws fonfigure # https://www.youtube.com/watch?v=IxA1IPypzHs


$ cat aws.tf

# https://www.terraform.io/docs/providers/aws/r/instance.html

resource "aws_instance" "ec2instance" {

ami = "${var.ami}"

instance_type = "t2.micro"

}


resource "aws_security_group" "instance_gc" {

}


$cat run.js

export AWS_ACCESS_KEY_ID="anaccesskey"

export AWS_SECRET_ACCESS_KEY="asecretkey"

export AWS_DEFAULT_REGION="us-west-2"

terraform plan

terraform apply


$ cat gce.tf # https://www.terraform.io/docs/providers/google/index.html#

# Google Cloud Platform Provider


provider "google" {

credentials = "${file("account.json")}"

project = "phalcon"

region = "us-central1"

}


#https://www.terraform.io/docs/providers/google/r/app_engine_application.html

resource "google_project" "my_project" {

name = "My Project"

project_id = "your-project-id"

org_id = "1234567"

}


resource "google_app_engine_application" "app" {

project = "${google_project.my_project.project_id}"

location_id = "us-central"

}


# google_compute_instance

resource "google_compute_instance" "default" {

name = "test"

machine_type = "n1-standard-1"

zone = "us-central1-a"


tags = ["foo", "bar"]


boot_disk {

initialize_params {

image = "debian-cloud/debian-9"

}

}


// Local SSD disk

scratch_disk {

}


network_interface {

network = "default"


access_config {

// Ephemeral IP

}

}


metadata = {

foo = "bar"

}


metadata_startup_script = "echo hi > /test.txt"


service_account {

scopes = ["userinfo-email", "compute-ro", "storage-ro"]

}

}


Расширяемость с помощью external resource, в качестве которого может быть скрипт на BASH:

data "external" "python3" {

program = ["Python3"]

}

Создание кластера машин с помощью Terraform

Создание кластера с помощью Terraform рассматривается в Создание инфраструктуры в GCP. Сейчас уделим больше внимания самому кластеру, а не инструментам по его созданию. Создам через панель администратора GCE проект (отображается в шапке интерфейса) node-cluster. Ключ для Kubernetes я скачал IAM и администрирование –> Сервисные аккаунты –> Создать сервисный аккаунт и при создании выбрал роль Владелец и положил в проект под названием kubernetes_key.JSON:

eSSH@Kubernetes-master:~/node-cluster$ cp ~/Downloads/node-cluster-243923-bbec410e0a83.JSON ./kubernetes_key.JSON

Скачал terraform:

essh@kubernetes-master:~/node-cluster$ wget https://releases.hashicorp.com/terraform/0.12.2/terraform_0.12.2_linux_amd64.zip >/dev/null 2>/dev/null

essh@kubernetes-master:~/node-cluster$ unzip terraform_0.12.2_linux_amd64.zip && rm -f terraform_0.12.2_linux_amd64.zip

Archive: terraform_0.12.2_linux_amd64.zip

inflating: terraform

essh@kubernetes-master:~/node-cluster$ ./terraform version

Terraform v0.12.2


Добавили провайдера GCE и запустил скачивание "драйверов" к нему:

essh@kubernetes-master:~/node-cluster$ cat main.tf

provider "google" {

credentials = "${file("kubernetes_key.json")}"

project = "node-cluster"

region = "us-central1"

}essh@kubernetes-master:~/node-cluster$ ./terraform init


Initializing the backend…


Initializing provider plugins…

– Checking for available provider plugins…

– Downloading plugin for provider "google" (terraform-providers/google) 2.8.0…


The following providers do not have any version constraints in configuration,

so the latest version was installed.


To prevent automatic upgrades to new major versions that may contain breaking

changes, it is recommended to add version = "…" constraints to the

corresponding provider blocks in configuration, with the constraint strings

suggested below.


* provider.google: version = "~> 2.8"


Terraform has been successfully initialized!


You may now begin working with Terraform. Try running "terraform plan" to see

any changes that are required for your infrastructure. All Terraform commands

should now work.


If you ever set or change modules or backend configuration for Terraform,

rerun this command to reinitialize your working directory. If you forget, other

commands will detect it and remind you to do so if necessary.

Добавлю виртуальную машину:

essh@kubernetes-master:~/node-cluster$ cat main.tf

provider "google" {

credentials = "${file("kubernetes_key.json")}"

project = "node-cluster-243923"

region = "europe-north1"

}

resource "google_compute_instance" "cluster" {

name = "cluster"

zone = "europe-north1-a"

machine_type = "f1-micro"


boot_disk {

initialize_params {

image = "debian-cloud/debian-9"

}

}


network_interface {

network = "default"

access_config {}

}


essh@kubernetes-master:~/node-cluster$ sudo ./terraform apply


An execution plan has been generated and is shown below.

Resource actions are indicated with the following symbols:

+ create


Terraform will perform the following actions:


# google_compute_instance.cluster will be created

+ resource "google_compute_instance" "cluster" {

+ can_ip_forward = false

+ cpu_platform = (known after apply)

+ deletion_protection = false

+ guest_accelerator = (known after apply)

+ id = (known after apply)

+ instance_id = (known after apply)

+ label_fingerprint = (known after apply)

+ machine_type = "f1-micro"

+ metadata_fingerprint = (known after apply)

+ name= "cluster"

+ project = (known after apply)

+ self_link = (known after apply)

+ tags_fingerprint = (known after apply)

+ zone= "europe-north1-a"


+ boot_disk {

+ auto_delete = true

+ device_name = (known after apply)

+ disk_encryption_key_sha256 = (known after apply)

+ source = (known after apply)


+ initialize_params {

+ image = "debian-cloud/debian-9"

+ size = (known after apply)

+ type = (known after apply)

}

}


+ network_interface {

+ address = (known after apply)

+ name = (known after apply)

+ network = "default"

+ network_ip = (known after apply)

+ subnetwork = (known after apply)

+ subnetwork_project = (known after apply)


+ access_config {

+ assigned_nat_ip = (known after apply)

+ nat_ip = (known after apply)

+ network_tier = (known after apply)

}

}


+ scheduling {

+ automatic_restart = (known after apply)

+ on_host_maintenance = (known after apply)

+ preemptible = (known after apply)


+ node_affinities {

+ key = (known after apply)

+ operator = (known after apply)

+ values = (known after apply)

}

}

}


Plan: 1 to add, 0 to change, 0 to destroy.


Do you want to perform these actions?

Terraform will perform the actions described above.

Only 'yes' will be accepted to approve.


Enter a value: yes


google_compute_instance.cluster: Creating…

google_compute_instance.cluster: Still creating… [10s elapsed]

google_compute_instance.cluster: Creation complete after 11s [id=cluster]


Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Добавлю к ноде публичный статический IP-адрес и SSH-ключ:

essh@kubernetes-master:~/node-cluster$ ssh-keygen -f node-cluster

Generating public/private rsa key pair.

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in node-cluster.