Quantcast
Channel: linux-notes.org
Viewing all 152 articles
Browse latest View live

Работа с AWS ELB и Terraform в Unix/Linux

$
0
0

Работа с AWS ELB и Terraform в Unix/Linux

Elastic Load Balancing — «резиновый лоад балансер», который  автоматически распределяет входящий трафик приложений на несколько нод ( например, на экземпляры EC2). Он контролирует хелз_чеки хостов и направляет трафик только на «здоровые» ноды. ELB поддерживает три типа балансиров нагрузки:

  • Application Load Balancers (ALB).
  • Network Load Balancers (NLB).
  • Classic Load Balancers (CLB или ELB).

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS ELB и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$ mkdir modules/elb

Переходим в нее:

$ cd modules/elb

Открываем файл:

$ vim elb.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS ELB
#---------------------------------------------------
resource "aws_elb" "elb" {
    name                = "${var.name}-elb-${var.environment}"
    #availability_zones  = ["${split(",", (lookup(var.availability_zones, var.region)))}"]
    security_groups     = ["${var.security_groups}"]
    subnets             = ["${var.subnets}"]
    internal            = false #"${var.elb_internal}"

    #instances                   = ["${var.instances}"]
    cross_zone_load_balancing   = "${var.cross_zone_load_balancing}"
    idle_timeout                = "${var.idle_timeout}"
    connection_draining         = "${var.connection_draining}"
    connection_draining_timeout = "${var.connection_draining_timeout}"

    access_logs                 = ["${var.access_logs}"]
    listener                    = ["${var.listener}"]
    health_check                = ["${var.health_check}"]

    tags {
        Name            = "${lower(var.name)}-elb-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
}
#---------------------------------------------------
# ELB attachment
#---------------------------------------------------
resource "aws_elb_attachment" "elb_attachment" {
    count       = "${length(var.instances)}"

    #elb         = "${var.name}-elb_attachment-${var.environment}"
    elb         = "${aws_elb.elb.name}"
    instance    = "${element(var.instances, count.index)}"

    depends_on  = ["aws_elb.elb"]
}
#---------------------------------------------------
# Add LB cookie stickiness policy
#---------------------------------------------------
resource "aws_lb_cookie_stickiness_policy" "lb_cookie_stickiness_policy_http" {
    name                        = "${var.name}-lb-cookie-stickiness-policy-http-${var.environment}"
    load_balancer               = "${aws_elb.elb.id}"
    lb_port                     = 80
    cookie_expiration_period    = 600

    depends_on                  = ["aws_elb.elb"]
}
#resource "aws_lb_cookie_stickiness_policy" "lb_cookie_stickiness_policy_https" {
#    name                        = "${var.name}-lb_cookie-stickiness-policy-https-${var.environment}"
#    load_balancer               = "${aws_elb.elb.id}"
#    lb_port                     = 443
#    cookie_expiration_period    = 600
#
#    depends_on                  = ["aws_elb.elb"]
#}
#---------------------------------------------------
#Add APP cookie stickiness policy
#---------------------------------------------------
resource "aws_app_cookie_stickiness_policy" "app_cookie_stickiness_policy_http" {
    name                     = "${var.name}-app-cookie-stickiness-policy-http-${var.environment}"
    load_balancer            = "${aws_elb.elb.id}"
    lb_port                  = 80
    cookie_name              = "JSESSIONID"

    depends_on               = ["aws_elb.elb"]
}
#resource "aws_app_cookie_stickiness_policy" "app_cookie_stickiness_policy_https" {
#    name                     = "${var.name}-app-cookie-stickiness-policy-https-${var.environment}"
#    load_balancer            = "${aws_elb.elb.id}"
#    lb_port                  = 443
#    cookie_name              = "JSESSIONID"
#
#    depends_on               = ["aws_elb.elb"]
#}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-ELB"
}
variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}
variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}
variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}
variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}
# Create ELB
variable "availability_zones" {
    description = "Availability zones for AWS ASG"
    type        = "map"
    default     = {
        us-east-1      = "us-east-1b,us-east-1c,us-east-1d,us-east-1e"
        us-east-2      = "us-east-2a,eu-east-2b,eu-east-2c"
        us-west-1      = "us-west-1a,us-west-1c"
        us-west-2      = "us-west-2a,us-west-2b,us-west-2c"
        ca-central-1   = "ca-central-1a,ca-central-1b"
        eu-west-1      = "eu-west-1a,eu-west-1b,eu-west-1c"
        eu-west-2      = "eu-west-2a,eu-west-2b"
        eu-central-1   = "eu-central-1a,eu-central-1b,eu-central-1c"
        ap-south-1     = "ap-south-1a,ap-south-1b"
        sa-east-1      = "sa-east-1a,sa-east-1c"
        ap-northeast-1 = "ap-northeast-1a,ap-northeast-1c"
        ap-southeast-1 = "ap-southeast-1a,ap-southeast-1b"
        ap-southeast-2 = "ap-southeast-2a,ap-southeast-2b,ap-southeast-2c"
        ap-northeast-1 = "ap-northeast-1a,ap-northeast-1c"
        ap-northeast-2 = "ap-northeast-2a,ap-northeast-2c"
    }
}
variable "security_groups" {
    description = "A list of security group IDs to assign to the ELB. Only valid if creating an ELB within a VPC"
    type        = "list"
    #default     = []
}
variable "subnets" {
    description = "A list of subnet IDs to attach to the ELB"
    type        = "list"
    default     = []
}
variable "instances" {
    description = " Instances ID to add them to ELB"
    type        = "list"
    default     = []
}
variable "elb_internal" {
    description = "If true, ELB will be an internal ELB"
    default     = false
}
variable "cross_zone_load_balancing" {
    description = "Enable cross-zone load balancing. Default: true"
    default     = true
}
variable "idle_timeout" {
    description = "The time in seconds that the connection is allowed to be idle. Default: 60"
    default     = "60"
}
variable "connection_draining" {
    description = "Boolean to enable connection draining. Default: false"
    default     = false
}
variable "connection_draining_timeout" {
    description = "The time in seconds to allow for connections to drain. Default: 300"
    default     = 300
}
# Access logs
variable "access_logs" {
    description = "An access logs block. Uploads access logs to S3 bucket"
    type        = "list"
    default     = []
}
# Listener
variable "listener" {
    description = "A list of Listener block"
    type        = "list"
}
# Health Check
variable "health_check" {
    description = " Health check"
    type        = "list"
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

и в него вставить нужно следующие строки:

# ELB
output "elb_id" {
  description = "The name of the ELB"
  value       = "${aws_elb.elb.id}"
}

output "elb_name" {
  description = "The name of the ELB"
  value       = "${aws_elb.elb.name}"
}

output "elb_dns_name" {
  description = "The DNS name of the ELB"
  value       = "${aws_elb.elb.dns_name}"
}

output "elb_instances" {
  description = "The list of instances in the ELB"
  value       = ["${aws_elb.elb.instances}"]
}

output "elb_source_security_group_id" {
  description = "The ID of the security group that you can use as part of your inbound rules for your load balancer's back-end application instances"
  value       = "${aws_elb.elb.source_security_group_id}"
}

output "elb_zone_id" {
  description = "The canonical hosted zone ID of the ELB (to be used in a Route 53 Alias record)"
  value       = "${aws_elb.elb.zone_id}"
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir elb && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region  = "us-east-1"
    # Make it faster by skipping something
    #skip_get_ec2_platforms      = true
    #skip_metadata_api_check     = true
    #skip_region_validation      = true
    #skip_credentials_validation = true
    #skip_requesting_account_id  = true
}
module "iam" {
    source                          = "../../modules/iam"
    name                            = "TEST-AIM2"
    region                          = "us-east-1"
    environment                     = "PROD"

    aws_iam_role-principals         = [
        "ec2.amazonaws.com",
    ]
    aws_iam_policy-actions           = [
        "cloudwatch:GetMetricStatistics",
        "logs:DescribeLogStreams",
        "logs:GetLogEvents",
        "elasticache:Describe*",
        "rds:Describe*",
        "rds:ListTagsForResource",
        "ec2:DescribeAccountAttributes",
        "ec2:DescribeAvailabilityZones",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeVpcs",
        "ec2:Owner",
    ]
}
module "vpc" {
    source                              = "../../modules/vpc"
    name                                = "main"
    environment                         = "PROD"
    # VPC
    instance_tenancy                    = "default"
    enable_dns_support                  = "true"
    enable_dns_hostnames                = "true"
    assign_generated_ipv6_cidr_block    = "false"
    enable_classiclink                  = "false"
    vpc_cidr                            = "172.31.0.0/16"
    private_subnet_cidrs                = ["172.31.64.0/20"]
    public_subnet_cidrs                 = ["172.31.0.0/20"]
    availability_zones                  = ["us-east-1a", "us-east-1b"]
    enable_all_egress_ports             = "true"
    allowed_ports                       = ["9300", "3272", "8888", "8444"]

    map_public_ip_on_launch             = "true"

    #Internet-GateWay
    enable_internet_gateway             = "true"
    #NAT
    enable_nat_gateway                  = "false"
    single_nat_gateway                  = "false"
    #VPN
    enable_vpn_gateway                  = "false"
    #DHCP
    enable_dhcp_options                 = "false"
    # EIP
    enable_eip                          = "false"
}
module "elb" {
    source                              = "../../modules/elb"
    name                                = "TEST-ELB"
    region                              = "us-east-1"
    environment                         = "PROD"

    security_groups                     = ["${module.vpc.security_group_id}"]

    # Need to choose subnets or availability_zones. The subnets has been chosen.
    subnets                             = ["${element(module.vpc.vpc-publicsubnet-ids, 0)}"]

    #access_logs = [
    #    {
    #        bucket = "my-access-logs-bucket"
    #        bucket_prefix = "bar"
    #        interval = 60
    #    },
    #]
    listener = [
        {
            instance_port     = "80"
            instance_protocol = "HTTP"
            lb_port           = "80"
            lb_protocol       = "HTTP"
        },
    #    {
    #        instance_port      = 80
    #        instance_protocol  = "http"
    #        lb_port            = 443
    #        lb_protocol        = "https"
    #        ssl_certificate_id = "${var.elb_certificate}"
    #    },
    ]
    health_check = [
        {
            target              = "HTTP:80/"
            interval            = 30
            healthy_threshold   = 2
            unhealthy_threshold = 2
            timeout             = 5
        },
    ]
}

PS: Тут имеются вспомогательные модули. Я описывал работу тут:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Вот может еще пригодится:

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Чуть позже, я опубликую весь материал на github аккаунты для удобства использования. Но об этом позже.

Вот и все на этом. Данная статья «Работа с AWS ELB и Terraform в Unix/Linux» завершена.


Работа с AWS Route53 и Terraform в Unix/Linux

$
0
0

Работа с AWS Route53 и Terraform в Unix/Linux

Amazon Route 53 – это высокодоступный и масштабируемый облачный веб-сервис системы доменных имен (DNS). Разработчики и владельцы веб-сервисов используют его как очень надежный и эффективный метод перенаправления конечных пользователей к интернет-приложениям, переводя доменные имена (например, www.example.com) в формат цифровых IP-адресов (например, 192.0.2.1), понятных для компьютеров. Amazon Route 53 также полностью совместим с протоколом IPv6.
Сервис Amazon Route 53 направляет запросы пользователей к инфраструктуре AWS, например к инстансам Amazon EC2, балансировщикам нагрузки Elastic Load Balancing или корзинам Amazon S3. Кроме того, он может использоваться для перенаправления пользователей в инфраструктуру за пределами AWS. Amazon Route 53 можно использовать как для организации подключений только к «здоровым» адресам (с использованием проверок DNS), так и для независимого мониторинга состояния приложения и его конечных точек. С помощью сервиса Amazon Route 53 Traffic Flow можно легко управлять глобальным трафиком, используя различные типы маршрутизации (такие как маршрутизация на базе задержки, DNS с учетом географического положения, географическая близость и циклический взвешенный алгоритм), которые можно сочетать с возможностью переброса сервиса DNS, создавая в результате отказоустойчивые архитектуры с низкой задержкой. Используя несложный визуальный редактор Amazon Route 53 Traffic Flow, можно легко управлять маршрутизацией конечных пользователей к конечным точкам ваших приложений как в рамках одного региона AWS, так и при распределении трафика по всему миру. Кроме того, в сервисе Amazon Route 53 можно зарегистрировать доменное имя: при покупке доменов (например, example.com) и управлении ими Amazon Route 53 автоматически настроит для них параметры DNS.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS ELB и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/route53

Переходим в нее:

$ cd modules/route53

Открываем файл:

$ vim route53.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS route53 zone(s)
#---------------------------------------------------
resource "aws_route53_zone" "primary_public" {
    count           = "${var.create_primary_public_route53_zone ? 1 : 0}"
    name            = "${var.domain_name_for_primary_public_route53_zone}"
    comment         = "Public zone for ${var.domain_name_for_primary_public_route53_zone}"
    tags {
        Name            = "${lower(var.name)}-route53_primary_public_zone-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }

}
#---------------------------------------------------
# Create AWS Route53 record(s)
#---------------------------------------------------
resource "aws_route53_record" "route53_record" {
    name    = "${var.route53_record_name}"
    zone_id = "${var.create_primary_public_route53_zone ? aws_route53_zone.primary_public.zone_id : var.parent_zone_id}"
    type    = "${var.route53_record_type}"
    #ttl     = "${var.route53_record_ttl}"
    #weighted_routing_policy {
    #    weight = 10
    #
    #}
    #set_identifier = "dev"
    #records = ["${var.route53_record_records}"]
    #failover_routing_policy {
    #    type = "PRIMARY"
    #}
    alias {
        name                   = "${var.target_dns_name}"
        zone_id                = "${var.target_zone_id}"
        evaluate_target_health = "${var.evaluate_target_health}"
    }
    depends_on  = ["aws_route53_zone.primary_public"]
}
#---------------------------------------------------
# Create AWS route53 health check(s)
#---------------------------------------------------
resource "aws_route53_health_check" "http_route53_health_check" {
    count             = "${var.create_http_route53_health_check ? 1 : 0}"

    fqdn              = "${var.fqdn_for_http_route53_health_check}"
    port              = "${var.port_for_http_route53_health_check}"
    type              = "${var.type_for_http_route53_health_check}"
    resource_path     = "${var.resource_path_for_http_route53_health_check}"
    failure_threshold = "${var.failure_threshold_for_http_route53_health_check}"
    request_interval  = "${var.request_interval_for_http_route53_health_check}"
    measure_latency   = "${var.measure_latency_for_http_route53_health_check}"

    tags {
        Name            = "${lower(var.name)}-http_route53_health_check-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
}
resource "aws_route53_health_check" "https_route53_health_check" {
    count             = "${var.create_https_route53_health_check ? 1 : 0}"

    fqdn              = "${var.fqdn_for_https_route53_health_check}"
    port              = "${var.port_for_https_route53_health_check}"
    type              = "${var.type_for_https_route53_health_check}"
    resource_path     = "${var.resource_path_for_https_route53_health_check}"
    failure_threshold = "${var.failure_threshold_for_https_route53_health_check}"
    request_interval  = "${var.request_interval_for_https_route53_health_check}"
    measure_latency   = "${var.measure_latency_for_https_route53_health_check}"

    tags {
        Name            = "${lower(var.name)}-https_route53_health_check-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
}

#---------------------------------------------------
# Create AWS api gateway domain name
#---------------------------------------------------
#resource "aws_api_gateway_domain_name" "example" {
#    domain_name = "api.example.com"
#
#    certificate_name        = "example-api"
#    certificate_body        = "${file("${path.module}/example.com/example.crt")}"
#    certificate_chain       = "${file("${path.module}/example.com/ca.crt")}"
#    certificate_private_key = "${file("${path.module}/example.com/example.key")}"
#}
# Example DNS record using Route53.
# Route53 is not specifically required; any DNS host can be used.
#resource "aws_route53_record" "example" {
#  zone_id = "${aws_route53_zone.example.id}" # See aws_route53_zone for how to create this
#
#  name = "${aws_api_gateway_domain_name.example.domain_name}"
#  type = "A"
#
#  alias {
#    name                   = "${aws_api_gateway_domain_name.example.cloudfront_domain_name}"
#    zone_id                = "${aws_api_gateway_domain_name.example.cloudfront_zone_id}"
#    evaluate_target_health = true
#  }
#}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-ASG"
}
variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}
variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}
variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}
variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}
# Route53
variable "create_primary_public_route53_zone" {
    description = " If true, then create primary public route53 zone;"
    default     = "false"
}
variable "domain_name_for_primary_public_route53_zone" {
    description = " Domain name for primary_public route53_zone"
    default     = "domain.localdomain"
}
variable "route53_record_name" {
    description = "Route53 record name"
    type        = "string"
    default     = ""
}
variable "route53_record_type" {
    description = "The record type. Valid values are A, AAAA, CAA, CNAME, MX, NAPTR, NS, PTR, SOA, SPF, SRV and TXT"
    default     = "A"
}
#variable "route53_record_ttl" {
#    description = "Route53 record ttl"
#    default     = "30"
#}
#variable "route53_record_records" {
#    description = "Route53 records"
#    type        = "list"
#    default     = []
#}
#variable "route53_zone_private_zone_internal" {
#    description = " Internal or external zone"
#    default     = "false"
#}
variable "parent_zone_id" {
    description = "Perent Zone ID"
    default     = ""
}
variable "target_dns_name" {
    description = "Target DNS name which needs to add to route53"
    #type        = "list"
    default     = ""
}
variable "target_zone_id" {
    description = "Target Zone ID which needs to add to route53"
    default     = ""
}
variable "evaluate_target_health" {
    description = "Set to true if you want Route 53 to determine whether to respond to DNS queries using this resource record set by checking the health of the resource record set"
    default     = "false"
}
variable "create_http_route53_health_check" {
    description = "Create http route53 health check"
    default     = "false"
}
variable "create_https_route53_health_check" {
    description = "Create https route53 health check"
    default     = "false"
}
variable "fqdn_for_http_route53_health_check" {
    description = "FQDN for http route53 health check"
    default     = ""
}
variable "fqdn_for_https_route53_health_check" {
    description = "FQDN for https route53 health check"
    default     = ""
}
variable "port_for_http_route53_health_check" {
    description = "Port for http route53 health check"
    default     = "80"
}
variable "port_for_https_route53_health_check" {
    description = "Port for https route53 health check"
    default     = "443"
}
variable "type_for_http_route53_health_check" {
    description = "Type for http route53 health check"
    default     = "HTTP"
}
variable "type_for_https_route53_health_check" {
    description = "Type for https route53 health check"
    default     = "HTTPS"
}
variable "resource_path_for_http_route53_health_check" {
    description = " Resource path for http route53 health check"
    default     = "/"
}
variable "resource_path_for_https_route53_health_check" {
    description = " Resource path for https route53 health check"
    default     = "/"
}
variable "failure_threshold_for_http_route53_health_check" {
    description = "Failure threshold for http route53 health check"
    default     = "5"
}
variable "failure_threshold_for_https_route53_health_check" {
    description = "Failure threshold for https route53 health check"
    default     = "5"
}
variable "request_interval_for_http_route53_health_check" {
    description = " Request interval for http route53 health check"
    default     = 30
}
variable "request_interval_for_https_route53_health_check" {
    description = " Request interval for https route53 health check"
    default     = 30
}
variable "measure_latency_for_http_route53_health_check" {
    description = "measure latency for http route53 health check"
    default     = "1"
}
variable "measure_latency_for_https_route53_health_check" {
    description = "measure latency for https route53 health check"
    default     = "1"
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "hostnames" {
    #value = "${aws_route53_record.route53_record.*.fqdn}"
    value = "${join("", aws_route53_record.route53_record.*.fqdn)}"
}
output "parent_zone_id" {
    #value = "${aws_route53_record.aws_route53_zone.primary_public.*.zone_id}"
    value = "${join("", aws_route53_record.route53_record.*.zone_id)}"
}
output "parent_zone_name" {
    value = "${join("", aws_route53_record.route53_record.*.name)}"
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir route53 && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region  = "us-east-1"
    # Make it faster by skipping something
    #skip_get_ec2_platforms      = true
    #skip_metadata_api_check     = true
    #skip_region_validation      = true
    #skip_credentials_validation = true
    #skip_requesting_account_id  = true
}
module "iam" {
    source                          = "../../modules/iam"
    name                            = "TEST-AIM2"
    region                          = "us-east-1"
    environment                     = "PROD"

    aws_iam_role-principals         = [
        "ec2.amazonaws.com",
    ]
    aws_iam_policy-actions           = [
        "cloudwatch:GetMetricStatistics",
        "logs:DescribeLogStreams",
        "logs:GetLogEvents",
        "elasticache:Describe*",
        "rds:Describe*",
        "rds:ListTagsForResource",
        "ec2:DescribeAccountAttributes",
        "ec2:DescribeAvailabilityZones",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeVpcs",
        "ec2:Owner",
    ]
}
module "vpc" {
    source                              = "../../modules/vpc"
    name                                = "main"
    environment                         = "PROD"
    # VPC
    instance_tenancy                    = "default"
    enable_dns_support                  = "true"
    enable_dns_hostnames                = "true"
    assign_generated_ipv6_cidr_block    = "false"
    enable_classiclink                  = "false"
    vpc_cidr                            = "172.31.0.0/16"
    private_subnet_cidrs                = ["172.31.64.0/20"]
    public_subnet_cidrs                 = ["172.31.0.0/20"]
    availability_zones                  = ["us-east-1a", "us-east-1b"]
    enable_all_egress_ports             = "true"
    allowed_ports                       = ["9300", "3272", "8888", "8444"]

    map_public_ip_on_launch             = "true"

    #Internet-GateWay
    enable_internet_gateway             = "true"
    #NAT
    enable_nat_gateway                  = "false"
    single_nat_gateway                  = "false"
    #VPN
    enable_vpn_gateway                  = "false"
    #DHCP
    enable_dhcp_options                 = "false"
    # EIP
    enable_eip                          = "false"
}
module "elb" {
    source                              = "../../modules/elb"
    name                                = "TEST-ELB"
    region                              = "us-east-1"
    environment                         = "PROD"

    security_groups                     = ["${module.vpc.security_group_id}"]

    # Need to choose subnets or availability_zones. The subnets has been chosen.
    subnets                             = ["${element(module.vpc.vpc-publicsubnet-ids, 0)}"]

    #access_logs = [
    #    {
    #        bucket = "my-access-logs-bucket"
    #        bucket_prefix = "bar"
    #        interval = 60
    #    },
    #]
    listener = [
        {
            instance_port     = "80"
            instance_protocol = "HTTP"
            lb_port           = "80"
            lb_protocol       = "HTTP"
        },
    #    {
    #        instance_port      = 80
    #        instance_protocol  = "http"
    #        lb_port            = 443
    #        lb_protocol        = "https"
    #        ssl_certificate_id = "${var.elb_certificate}"
    #    },
    ]
    health_check = [
        {
            target              = "HTTP:80/"
            interval            = 30
            healthy_threshold   = 2
            unhealthy_threshold = 2
            timeout             = 5
        },
    ]
}
module "asg" {
    source                              = "../../modules/asg"
    name                                = "TEST-ASG"
    region                              = "us-east-1"
    environment                         = "PROD"

    security_groups = ["${module.vpc.security_group_id}"]

    root_block_device  = [
        {
            volume_size = "8"
            volume_type = "gp2"
        },
    ]

    # Auto scaling group
    #asg_name                  = "example-asg"
    vpc_zone_identifier       = ["${module.vpc.vpc-publicsubnet-ids}"]
    health_check_type         = "EC2"
    asg_min_size              = 0
    asg_max_size              = 1
    desired_capacity          = 1
    wait_for_capacity_timeout = 0

    load_balancers            = ["${module.elb.elb_name}"]

    #
    enable_autoscaling_schedule = true
}
module "route53" {
    source                              = "../../modules/route53"
    name                                = "TEST-ASG"
    region                              = "us-east-1"
    environment                         = "PROD"

    create_primary_public_route53_zone          = "true"
    domain_name_for_primary_public_route53_zone = "example.local"

    route53_record_name     = "Test-domain.local"
    #route53_record_type     = "A"
    #route53_record_ttl      = "60"
    #route53_record_records  = ["192.168.0.114"]

    #parent_zone_id          = "Z254KLT7VYA1UX"

    target_dns_name         = "${module.elb.elb_dns_name}"
    target_zone_id          = "${module.elb.elb_zone_id}"

    evaluate_target_health  = "true"

    #Health_checks
    #create_http_route53_health_check    = "true"
    fqdn_for_http_route53_health_check       = "linux-notes.org"

    #create_https_route53_health_check   = "true"
    fqdn_for_https_route53_health_check = "linux-notes.org"
}

PS: Тут имеются вспомогательные модули. Я описывал работу тут:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с AWS ELB и Terraform в Unix/Linux» завершена.

Работа с AWS RDS и Terraform в Unix/Linux

$
0
0

Работа с AWS RDS и Terraform в Unix/Linux

Amazon Relational Database Service (Amazon RDS) позволяет легко настраивать, использовать и масштабировать реляционные базы данных в облаке. Сервис обеспечивает экономичное и масштабируемое использование ресурсов при одновременной автоматизации трудоемких задач администрирования, таких как выделение аппаратного обеспечения, настройка базы данных, установка исправлений и резервное копирование. Это позволяет сосредоточить внимание на приложениях, чтобы обеспечить необходимые им высокую производительность, высокую доступность, безопасность и совместимость.

Amazon RDS доступен в виде инстансов базы данных нескольких типов: оптимизированные по использованию памяти, по производительности или выполнению операций ввода-вывода – и позволяет на выбор использовать шесть известных ядер баз данных, в том числе Amazon Aurora, PostgreSQL, MySQL, MariaDB, Oracle и Microsoft SQL Server. Можно использовать AWS Database Migration Service, чтобы легко переносить или реплицировать существующие базы данных в Amazon RDS.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS RDS и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/rds

Переходим в нее:

$ cd modules/rds

Открываем файл:

$ vim rds.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS RDS instance(s)
#---------------------------------------------------
resource "aws_db_instance" "db_instance" {
    count                = "${var.create_rds_cluster ? 0 : var.number_of_instances_in_the_cluster}"

    identifier                  = "${lower(var.name)}-rds-${lower(var.environment)}-${count.index+1}"
    allocated_storage           = "${var.allocated_storage}"
    storage_type                = "${var.storage_type}"
    iops                        = "${var.iops}"
    engine                      = "${var.engine}"
    engine_version              = "${var.engine_version}"
    instance_class              = "${var.instance_class}"
    replicate_source_db         = "${var.replicate_source_db}"
    backup_retention_period     = "${var.backup_retention_period}"
    backup_window               = "${var.backup_window}"
    copy_tags_to_snapshot       = "${var.copy_tags_to_snapshot}"
    skip_final_snapshot         = "${var.skip_final_snapshot}"
    final_snapshot_identifier   = "${lower(var.name)}-rds-${lower(var.environment)}-${md5(timestamp())}"

    name                    = "${var.db_name}"
    username                = "${var.db_username}"
    password                = "${var.db_password}"
    #port                    = "${var.db_port}"
    port                    = "${lookup(var.default_ports, var.engine)}"
    character_set_name      = "${var.character_set_name}"

    vpc_security_group_ids  = ["${var.vpc_security_group_ids}"]
    db_subnet_group_name    = "${var.db_subnet_group_name}"
    parameter_group_name    = "${var.parameter_group_name}"
    #parameter_group_name    = "${length(var.parameter_group_name) > 0 ? var.parameter_group_name : aws_db_parameter_group.db_parameter_group_instance.id}"
    publicly_accessible     = "${var.publicly_accessible}"
    storage_encrypted       = "${var.storage_encrypted}"
    multi_az                = "${var.multi_az}"

    allow_major_version_upgrade = "${var.allow_major_version_upgrade}"
    auto_minor_version_upgrade  = "${var.auto_minor_version_upgrade}"
    apply_immediately           = "${var.apply_immediately}"
    maintenance_window          = "${var.maintenance_window}"

    monitoring_interval = "${var.monitoring_interval}"

    tags {
        Name            = "${var.name}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }

    lifecycle {
        create_before_destroy   = true,
        ignore_changes          = ["final_snapshot_identifier", "replicate_source_db"],
    }

    #depends_on  = ["aws_db_parameter_group.db_parameter_group_instance"]
}
#---------------------------------------------------
# Create AWS RDS cluster
#---------------------------------------------------
resource "aws_rds_cluster_instance" "rds_cluster_instance" {
    count               = "${var.create_rds_cluster ? var.number_of_instances_in_the_cluster : 0}"

    identifier          = "${lower(var.name)}-cluster-${lower(var.environment)}-${count.index+1}"
    cluster_identifier  = "${aws_rds_cluster.rds_cluster.id}"
    instance_class      = "${var.instance_class}"

    db_subnet_group_name    = "${var.db_subnet_group_name == "" ? aws_db_subnet_group.db_subnet_group.id : var.db_subnet_group_name}"
    #db_subnet_group_name    = "aws_db_subnet_group.db_subnet_group.id"
    apply_immediately       = "${var.apply_immediately}"
    db_parameter_group_name = "${var.instance_parameter_group_name == "" ? aws_db_parameter_group.db_parameter_group.id : var.instance_parameter_group_name}"

    tags {
        Name            = "${lower(var.name)}-cluster-${lower(var.environment)}-${count.index+1}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }

    depends_on          = ["aws_rds_cluster.rds_cluster", "aws_db_subnet_group.db_subnet_group", "aws_db_parameter_group.db_parameter_group"]
}

resource "aws_rds_cluster" "rds_cluster" {
    count               = "${var.create_rds_cluster ? 1 : 0}"

    cluster_identifier  = "${lower(var.name)}-cluster-${lower(var.environment)}"
    engine                      = "${var.engine}"
    engine_version              = "${var.engine_version}"

    backup_retention_period     = "${var.backup_retention_period}"
    preferred_backup_window     = "${var.backup_window}"
    skip_final_snapshot         = "${var.skip_final_snapshot}"
    final_snapshot_identifier   = "${lower(var.name)}-cluster-${lower(var.environment)}-${md5(timestamp())}"

    #db_subnet_group_name            = "${var.db_subnet_group_name}"
    db_subnet_group_name            = "${aws_db_subnet_group.db_subnet_group.id}"
    vpc_security_group_ids          = ["${var.vpc_security_group_ids}"]

    storage_encrypted               = "${var.storage_encrypted}"
    apply_immediately               = "${var.apply_immediately}"
    db_cluster_parameter_group_name = "${var.db_cluster_parameter_group_name}"

    availability_zones  = ["${split(",", (lookup(var.availability_zones, var.region)))}"]

    database_name       = "${var.db_name}"
    master_username     = "${var.db_username}"
    master_password     = "${var.db_password}"

    tags {
        Name            = "${lower(var.name)}-cluster-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }

    lifecycle {
        create_before_destroy   = true,
        ignore_changes          = ["final_snapshot_identifier"],
  }
}
#---------------------------------------------------
# Create AWS DB subnet group
#---------------------------------------------------
resource "aws_db_subnet_group" "db_subnet_group" {
    count       = "${var.create_rds_cluster ? 1 : 0}"

    name        = "${lower(var.name)}-db_subnet_group-${lower(var.environment)}"
    description = "My ${lower(var.name)}-db_subnet_group-${lower(var.environment)} group of subnets"
    subnet_ids  = ["${var.subnet_ids}"]

    tags {
        Name            = "${lower(var.name)}-db_subnet_group-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
  }
}
#---------------------------------------------------
# Create AWS DB parameter group
#---------------------------------------------------
resource "aws_db_parameter_group" "db_parameter_group" {
    count       = "${var.create_rds_cluster ? 1 : 0}"

    name        = "${lower(var.name)}-db-parameter-group-${lower(var.environment)}"
    family      = "aurora5.6"
    description = "${var.name} ${var.environment} parameter group for ${var.engine}"

    parameter = {
        name = "slow_query_log"
        value = "1"
    }
    parameter = {
        name = "long_query_time"
        value = "1"
    }
    parameter = {
        name = "general_log"
        value = "0"
    }
    parameter = {
        name = "log_output"
        value = "FILE"
    }

    tags {
        Name            = "${lower(var.name)}-db_parameter_group-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
}
#
# Not finished yet..... It's not working and don't use in this module at all........
#
resource "aws_db_parameter_group" "db_parameter_group_instance" {
    count       = "${length(var.parameter_group_name) > 0 ? 0 : 1}"

    #name_prefix = "${lower(var.name)}-${lower(var.environment)}-"
    name        = "${lower(var.name)}-db_parameter_group_instance-${lower(var.environment)}"
    description = "RDS ${lower(var.name)}-db_parameter_group_instance-${lower(var.environment)} parameter group for ${var.engine}"
    family      = "mysql5.7"
    parameter   = "${var.default_db_parameters[var.engine]}"
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-RDS"
}
variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}
variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}
variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}
variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}
variable "create_rds_cluster" {
    description = "If true, then rds cluster will create"
    default     = false
}
variable "number_of_instances_in_the_cluster" {
    description = "Number of nodes in the cluster"
    default     = "1"
}
variable "db_cluster_parameter_group_name" {
    description = "A cluster parameter group to associate with the cluster."
    default     = ""
}
variable "instance_parameter_group_name" {
    description = "A instance parameter group to associate"
    default     = ""
}
variable "subnet_ids" {
    description = "subnet IDs"
    type        = "list"
}
variable "identifier" {
    description = "The name of the RDS instance, if omitted, Terraform will assign a random, unique identifier."
    default     = ""
}
variable "identifier_prefix" {
    description = "Creates a unique identifier beginning with the specified prefix. Conflicts with identifer."
    default     = ""
}
variable "allocated_storage" {
    description = "The allocated storage in gigabytes."
    default     = "20"
}
variable "storage_type" {
    description = "One of 'standard' (magnetic), 'gp2' (general purpose SSD), or 'io1' (provisioned IOPS SSD). The default is 'io1' if iops is specified, 'standard' if not. Note that this behaviour is different from the AWS web console, where the default is 'gp2'."
    default     = "gp2"
}
variable "iops" {
    description = "The amount of provisioned IOPS. Setting this implies a storage_type of 'io1', default is 0 if rds storage type is not io1"
    default     = "0"
}
variable "engine" {
    description = "The database engine to use (mysql, postgres etc)"
    default     = "mysql"
}
variable "engine_version" {
    description = "The engine version to use."
    default     = "5.6.37"
}
variable "instance_class" {
    description = "The instance type of the RDS instance."
    default     = "db.t2.micro"
}
variable "db_name" {
    description = "The name of the database to create when the DB instance is created. If this parameter is not specified, no database is created in the DB instance. Note that this does not apply for Oracle or SQL Server engines."
    default     = "db_name_test"
}
variable "db_username" {
    description = "Username for the master DB user."
    default     = "root"
}
variable "db_password" {
    description = "Password for the master DB user. Note that this may show up in logs, and it will be stored in the state file."
    default     = "ROot666roOT"
}
variable "db_port" {
    description = "The database port (3306 etc)"
    default     = "3306"
}
variable "default_ports" {
    description = "Default database ports"
    type        = "map"
    default     = {
        mysql    = "3306"
        postgres = "5432"
        oracle   = "1521"
    }
}
#lookup parameters for specic RDS types
variable "default_db_parameters" {
    default = {
        mysql = [
            {
                name  = "slow_query_log"
                value = "1"
            },
            {
                name  = "long_query_time"
                value = "1"
            },
            {
                name  = "general_log"
                value = "0"
            },
            {
                name  = "log_output"
                value = "FILE"
            },
            {
                name  = "character_set_server"
                value = "utf8"
            },
            {
                name  = "character_set_client"
                value = "utf8"
            },
        ]
        postgres = []
        oracle   = []
    }
}
variable "character_set_name" {
    description = "The character set name to use for DB encoding in Oracle instances. This can't be changed"
    #default     = "utf8"
    default     = ""
}
variable "db_subnet_group_name" {
    description = "Name of DB subnet group. DB instance will be created in the VPC associated with the DB subnet group. If unspecified, will be created in the default VPC, or in EC2 Classic, if available."
    default     = ""
}
variable "parameter_group_name" {
    description = "Name of the DB parameter group to associate."
    default     = "default.mysql5.6"
}
variable "publicly_accessible" {
    description = "Bool to control if instance is publicly accessible. Default is false."
    default     = "false"
}
variable "storage_encrypted" {
    description = "Specifies whether the DB instance is encrypted. The default is false if not specified."
    default     = "false"
}
variable "vpc_security_group_ids" {
    description = "List of VPC security groups to associate."
    type        = "list"
    default     = []
}
variable "iam_database_authentication_enabled" {
    description = "Specifies whether or mappings of AWS Identity and Access Management (IAM) accounts to database accounts is enabled."
    default     = []
}
variable "availability_zones" {
    description = "Availability zones for AWS ASG"
    type        = "map"
    default     = {
        us-east-1      = "us-east-1b,us-east-1a"
        us-east-2      = "us-east-2a,eu-east-2b,eu-east-2c"
        us-west-1      = "us-west-1a,us-west-1c"
        us-west-2      = "us-west-2a,us-west-2b,us-west-2c"
        ca-central-1   = "ca-central-1a,ca-central-1b"
        eu-west-1      = "eu-west-1a,eu-west-1b,eu-west-1c"
        eu-west-2      = "eu-west-2a,eu-west-2b"
        eu-central-1   = "eu-central-1a,eu-central-1b,eu-central-1c"
        ap-south-1     = "ap-south-1a,ap-south-1b"
        sa-east-1      = "sa-east-1a,sa-east-1c"
        ap-northeast-1 = "ap-northeast-1a,ap-northeast-1c"
        ap-southeast-1 = "ap-southeast-1a,ap-southeast-1b"
        ap-southeast-2 = "ap-southeast-2a,ap-southeast-2b,ap-southeast-2c"
        ap-northeast-1 = "ap-northeast-1a,ap-northeast-1c"
        ap-northeast-2 = "ap-northeast-2a,ap-northeast-2c"
    }
}
variable "backup_retention_period" {
    description = "The backup retention period (in days)"
    default     = "0"
}
variable "backup_window" {
    description = "The daily time range (in UTC) during which automated backups are created if they are enabled. Example: '09:46-10:16'. Must not overlap with maintenance_window."
    ## 12:00AM-12:30AM ET
    default     = "09:00-09:30"
}
variable "maintenance_window" {
    description = "The daily time range (in UTC) during which maintenance window are enabled. Must not overlap with backup_window."
    # SUN 12:30AM-01:30AM ET
    default = "sun:04:30-sun:05:30"
}
variable "monitoring_interval" {
    description = "To disable collecting Enhanced Monitoring metrics, specify 0. The default is 0. Valid Values: 0, 1, 5, 10, 15, 30, 60."
    default     = "0"
}
variable "replicate_source_db" {
    description = "Specifies that this resource is a Replicate database, and to use this value as the source database. This correlates to the identifier of another Amazon RDS Database to replicate."
    default     = ""
}
variable "skip_final_snapshot" {
    description = "Determines whether a final DB snapshot is created before the DB instance is deleted. If true is specified, no DBSnapshot is created. If false is specified, a DB snapshot is created before the DB instance is deleted, using the value from final_snapshot_identifier. Default is false."
    default     = "false"
}
variable "copy_tags_to_snapshot" {
    description = "On delete, copy all Instance tags to the final snapshot (if final_snapshot_identifier is specified). Default is false."
    default     = "false"
}
#variable "final_snapshot_identifier" {
#    description = "The name of your final DB snapshot when this DB instance is deleted. If omitted, no final snapshot will be made."
#    default     = "2018"
#}
variable "multi_az" {
    description = "If the RDS instance is multi AZ enabled."
    default     = "false"
}
variable "allow_major_version_upgrade" {
    description = "Indicates that major version upgrades are allowed. Changing this parameter does not result in an outage and the change is asynchronously applied as soon as possible."
    default     = "true"
}
variable "auto_minor_version_upgrade" {
    description = "Indicates that minor engine upgrades will be applied automatically to the DB instance during the maintenance window. Defaults to true."
    default     = "false"
}
variable "apply_immediately" {
    description = "Specifies whether any database modifications are applied immediately, or during the next maintenance window. Default is false"
    default     = "false"
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

и в него вставить нужно следующие строки:

output "rds_ids" {
    value = "${aws_db_instance.db_instance.*.id}"
}
output "rds_arns" {
    value = "${aws_db_instance.db_instance.*.arn}"
}
output "rds_addresses" {
    value = "${aws_db_instance.db_instance.*.address}"
}
output "endpoints" {
    value = "${aws_rds_cluster.rds_cluster.*.endpoint}"
}
output "reader_endpoints" {
    value = "${aws_rds_cluster.rds_cluster.*.reader_endpoint}"
}
output "aws_db_subnet_group_ids" {
    value = "${aws_db_subnet_group.db_subnet_group.*.id}"
}
output "db_parameter_groups" {
    value = "aws_db_parameter_group.db_parameter_group.*.id"
}
output "hosted_zone_ids" {
    value = "${aws_db_instance.db_instance.*.hosted_zone_id}"
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir rds && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region  = "us-east-1"
    # alias = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
     # access_key = "${var.aws_access_key}"
     # secret_key = "${var.aws_secret_key}"
}
module "iam" {
    source                          = "../../modules/iam"
    name                            = "TEST-AIM2"
    region                          = "us-east-1"
    environment                     = "PROD"

    aws_iam_role-principals         = [
        "ec2.amazonaws.com",
    ]
    aws_iam_policy-actions           = [
        "cloudwatch:GetMetricStatistics",
        "logs:DescribeLogStreams",
        "logs:GetLogEvents",
        "rds:*",
    ]
}
module "vpc" {
    source                              = "../../modules/vpc"
    name                                = "main"
    environment                         = "PROD"
    # VPC
    instance_tenancy                    = "default"
    enable_dns_support                  = "true"
    enable_dns_hostnames                = "true"
    assign_generated_ipv6_cidr_block    = "false"
    enable_classiclink                  = "false"
    vpc_cidr                            = "172.31.0.0/16"
    private_subnet_cidrs                = ["172.31.64.0/20"]
    public_subnet_cidrs                 = ["172.31.0.0/20"]
    availability_zones                  = ["us-east-1a", "us-east-1b"]
    enable_all_egress_ports             = "true"
    allowed_ports                       = ["80", "3306", "8080", "443"]

    map_public_ip_on_launch             = "true"

    #Internet-GateWay
    enable_internet_gateway             = "true"
    #NAT
    enable_nat_gateway                  = "false"
    single_nat_gateway                  = "false"
    #VPN
    enable_vpn_gateway                  = "false"
    #DHCP
    enable_dhcp_options                 = "false"
    # EIP
    enable_eip                          = "false"
}
module "rds" {
    source              = "../../modules/rds"
    name                = "Test-DB"
    region              = "us-east-1"
    environment         = "PROD"

    subnet_ids          = ["subnet-11ed234b", "subnet-34eddf51"]

    #create_rds_cluster  = true
    #
    ## For cluster
    ## aurora or aurora-postgresql. !!!!Tested just for aurora!!!!
    #engine              = "aurora"
    #engine_version      = "1.14.1"
    #subnet_ids          = ["subnet-11ed234b", "subnet-34eddf51"]
    ##subnet_ids          = ["module.vpc.vpc-privatesubnet-ids"]
    #instance_class      = "db.t2.small"
}

PS: Тут имеются вспомогательные модули. Я описывал работу тут:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Еще полезности:

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Чуть позже, я опубликую весь материал на github аккаунты для удобства использования. Но об этом позже.

Вот и все на этом. Данная статья «Работа с AWS RDS и Terraform в Unix/Linux» завершена.

 

Работа с AWS S3 и Terraform в Unix/Linux

$
0
0

Работа с AWS S3 и Terraform в Unix/Linux

Amazon S3 – (Amazon Simple Storage Service) — это объектное хранилище, предназначенное для хранения и извлечения любых объемов данных из любых источников: веб-сайтов и мобильных приложений, корпоративных приложений, а также данных с датчиков или устройств IoT. Сервис гарантирует надежность хранения на уровне 99,999999999 % и используется для хранения данных миллионами приложений, применяемых лидерами рынка во всех отраслях. S3 открывает широчайшие возможности для обеспечения безопасности и соответствия согласно самым строгим нормативным требованиям. Сервис дарит клиентам гибкость в управлении данными, обеспечивая оптимизацию затрат, контроль доступа и соответствие требованиям. S3 предоставляет функциональные возможности для выполнения запросов к данным без извлечения, что позволяет использовать мощные аналитические инструменты для непосредственной обработки данных, хранимых в S3. Amazon S3 – это самая поддерживаемая из доступных платформ хранения с наиболее широкой экосистемой решений сторонних независимых поставщиков (ISV) и партнеров по интеграции решений.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS S3 и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/s3

Переходим в нее:

$ cd modules/s3

Открываем файл:

$ vim s3.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create S3 bucket
#---------------------------------------------------
resource "aws_s3_bucket" "s3_bucket" {
    #count  = ""
    #bucket_prefix = "${var.bucket_prefix}"
    bucket = "${lower(var.name)}-s3-${lower(var.environment)}"
    region = "${var.region}"

    acl    = "${var.s3_acl}"
    policy = "${file("${path.module}/policies/${var.s3_acl}-policy.json")}"
    #Add website
    website     = "${var.website}"
    #Add cors rules
    cors_rule   = "${var.cors_rule}"
    #Add logging
    logging {
        target_bucket = "${lower(var.name)}-s3-${lower(var.environment)}"
        target_prefix = "/log"
    }
    #Add versioning
    versioning {
        enabled = "${var.versioning}"
    }
    #Add lifecycle rule
    lifecycle_rule  = "${var.lifecycle_rule}"

    #Add server side encryption configuration
    server_side_encryption_configuration {
        rule {
            apply_server_side_encryption_by_default {
                kms_master_key_id = "${aws_kms_key.kms_key.arn}"
                sse_algorithm     = "aws:kms"
            }
        }
    }

    force_destroy   = "${var.force_destroy}"

    tags {
        Name            = "${lower(var.name)}-s3-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
    lifecycle {
        create_before_destroy = true
    }

    depends_on  = ["aws_kms_key.kms_key"]
}
#---------------------------------------------------
# Create AWS KMS key
#---------------------------------------------------
resource "aws_kms_key" "kms_key" {
    #count                   = "${var.enable_default_server_side_encryption ? 1 : 0}"
    description             = "This key is used to encrypt bucket objects"
    deletion_window_in_days = 10
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-S3"
}
variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}
variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}
variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}
variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}
variable "bucket_prefix" {
    description = "Creates a unique bucket name beginning with the specified prefix. Conflicts with bucket."
    default     = ""
}
variable "s3_acl" {
    description = "The canned ACL to apply. Defaults to 'private'."
    default     = "private"
}
variable "versioning" {
    description = "A state of versioning"
    default = false
}
variable "force_destroy" {
    description = "A boolean that indicates all objects should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable."
    default = false
}
variable "website" {
    description = "List of website fields"
    type        = "list"
    default     = []
}
variable "routing_rules" {
    description = "Routing rules"
    type        = "list"
    default     = []
}
variable "cors_rule" {
    description = "Cors rules"
    type        = "list"
    default     = []
}
variable "logging" {
    description = "Add logging rules"
    type        = "list"
    default     = []
}
variable "lifecycle_rule" {
    description = "Add lifecycle rules"
    type        = "list"
    default     = []
}
#variable "enable_default_server_side_encryption" {
#    description = "enable default server side encryption"
#    default = false
#}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "bucket_ids" {
    description = "bucket_id"
    value       = "${aws_s3_bucket.s3_bucket.*.id}"
}
//the arn of the bucket that was created
output "bucket_arns" {
    value = "${aws_s3_bucket.s3_bucket.*.arn}"
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir s3 && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region  = "us-east-1"
    # alias = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
     # access_key = "${var.aws_access_key}"
     # secret_key = "${var.aws_secret_key}"
}

module "s3" {
    source                              = "../../modules/s3"
    name                                = "My-backet"
    environment                         = "PROD"

    #
    s3_acl          = "log-delivery-write"  #"private"
    force_destroy   = "true"
    # Allow public web-site (Static website hosting)
    website         = [
    {
        index_document = "index.html"
        error_document = "error.html"
    },
    ]
    # Use cors rules
    cors_rule       = [
    {
        allowed_headers = ["*"]
        allowed_methods = ["PUT", "POST"]
        allowed_origins = ["https://s3-website.linux-notes.org"]
        expose_headers  = ["ETag"]
        max_age_seconds = 3000
    },
    ]


}

PS: Тут имеются вспомогательные модули. Я описывал работу тут:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Еще полезности:

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Чуть позже, я опубликую весь материал на github аккаунты для удобства использования. Но об этом позже.

Вот и все на этом. Данная статья «Работа с AWS S3 и Terraform в Unix/Linux» завершена.

Работа с AWS SNS и Terraform в Unix/Linux

$
0
0

Работа с AWS SNS и Terraform в Unix/Linux

Amazon Simple Notification Service (SNS) – гибкий, полностью управляемый сервис передачи сообщений по модели «издатель-подписчик» и уведомлений для мобильных устройств, который позволяет координировать доставку сообщений подписанным конечным точкам и клиентам. С помощью SNS можно рассылать сообщения большому количеству подписчиков, включая распределенные системы и сервисы, а также мобильные устройства. Сервис легко настраивается и прост в работе. Он позволяет надежно отправлять уведомления всем конечным точкам при любых масштабах. Начать работу с SNS можно за несколько минут, используя Консоль управления AWS, интерфейс командной строки AWS или AWS SDK всего с тремя простыми API. SNS позволяет забыть про сложности и дополнительные расходы, связанные с обслуживанием выделенного ПО и инфраструктуры для отправки сообщений, а также с управлением таковыми.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS SNS и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/sns

Переходим в нее:

$ cd modules/sns

Открываем файл:

$ vim sns.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS SNS topic
#---------------------------------------------------
resource "aws_sns_topic" "sns_topic" {
    #name_prefix = "${lower(var.name)}-sns-"
    name            = "${lower(var.name)}-sns-${lower(var.environment)}"
    display_name    = "${lower(var.name)}-sns-${lower(var.environment)}"
    delivery_policy = "${data.template_file.sns_topic_delivery_policy_document.rendered}"

    depends_on = ["data.template_file.sns_topic_delivery_policy_document"]
}

data "template_file" "sns_topic_delivery_policy_document" {

    template = "${file("${path.module}/policies/sns_topic_delivery_policy_document.json.tpl")}"

    vars {
        minDelayTarget                  = "${var.minDelayTarget}"
        maxDelayTarget                  = "${var.maxDelayTarget}"
        numRetries                      = "${var.numRetries}"
        numMaxDelayRetries              = "${var.numMaxDelayRetries}"
        numNoDelayRetries               = "${var.numNoDelayRetries}"
        numMinDelayRetries              = "${var.numMinDelayRetries}"
        backoffFunction                 = "${var.backoffFunction}"
        disableSubscriptionOverrides    = "${var.disableSubscriptionOverrides}"
    }

}
#---------------------------------------------------
# Create AWS SNS topic policies
#---------------------------------------------------
resource "aws_sns_topic_policy" "sns_topic_policy" {
    arn             = "${aws_sns_topic.sns_topic.arn}"
    policy          = "${data.aws_iam_policy_document.sns_topic_policy_document.json}"

    depends_on  = ["aws_sns_topic.sns_topic", "data.aws_iam_policy_document.sns_topic_policy_document"]
}

data "aws_iam_policy_document" "sns_topic_policy_document" {
    policy_id = "__default_policy_ID"

    statement {
        actions = [
            "SNS:Subscribe",
            "SNS:SetTopicAttributes",
            "SNS:RemovePermission",
            "SNS:Receive",
            "SNS:Publish",
            "SNS:ListSubscriptionsByTopic",
            "SNS:GetTopicAttributes",
            "SNS:DeleteTopic",
            "SNS:AddPermission",
        ]

        condition {
            test     = "StringEquals"
            variable = "AWS:SourceOwner"

            values = [
                "${var.account-id}",
            ]
        }

        effect = "Allow"

        principals {
            type        = "AWS"
            identifiers = ["*"]
        }

        resources = [
            "${aws_sns_topic.sns_topic.arn}",
        ]

        sid = "__default_statement_ID"
    }

}
#---------------------------------------------------
# Create AWS SNS topic subscription
#---------------------------------------------------
resource "aws_sns_topic_subscription" "sns_topic_subscription" {
    topic_arn = "${aws_sns_topic.sns_topic.id}"

    confirmation_timeout_in_minutes = "${var.confirmation_timeout_in_minutes}"
    endpoint_auto_confirms          = "${var.endpoint_auto_confirms}"
    raw_message_delivery            = "${var.raw_message_delivery}"

    protocol  = "${var.sns_protocol}"
    endpoint  = "${var.sns_endpoint}"

    depends_on = ["aws_sns_topic.sns_topic"]
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-SNS"
}

variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}

variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}

variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}

variable "account-id" {
    description = "Account ID"
    default     = ""
}

variable "delivery_policy" {
    description = "Delivery policy"
    default     = ""
}

variable "sns_protocol" {
    description = "The protocol to use. The possible values for this are: sqs, sms, lambda, application. (http or https are partially supported, see below) (email is option but unsupported, see below)."
    default     = "sqs"
}

variable "sns_endpoint" {
    description = "The endpoint to send data to, the contents will vary with the protocol. (see below for more information)"
    default     = ""
}

variable "confirmation_timeout_in_minutes" {
    description = "Set timeout in minutes. Integer indicating number of minutes to wait in retying mode for fetching subscription arn before marking it as failure. Only applicable for http and https protocols (default is 1 minute)."
    default     = "1"
}

variable "endpoint_auto_confirms" {
    description = "Enable endpoint auto confirms. Boolean indicating whether the end point is capable of auto confirming subscription e.g., PagerDuty (default is false)"
    default     = "false"
}

variable "raw_message_delivery" {
    description = "Set raw message delivery.Boolean indicating whether or not to enable raw message delivery (the original message is directly passed, not wrapped in JSON with the original message in the message property) (default is false)."
    default     = "false"
}

#Delivery policies
variable "minDelayTarget" {
    description = "Set minDelayTarget. Max=20"
    default     = "19"
}

variable "maxDelayTarget" {
    description = "Set maxDelayTarget. Max=20"
    default     = "19"
}

variable "numRetries" {
    description = ""
    default     = "3"
}

variable "numMaxDelayRetries" {
    description = ""
    default     = "0"
}

variable "numNoDelayRetries" {
    description = ""
    default     = "0"
}

variable "numMinDelayRetries" {
    description = ""
    default     = "0"
}

variable "backoffFunction" {
    description = "Set backoffFunction. Can set: arithmetic, exponential or linear."
    default     = "linear"
}

variable "disableSubscriptionOverrides" {
    description = ""
    default     = "false"
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "sns_topic_id" {
    value = "${aws_sns_topic.sns_topic.id}"
}

output "sns_topic_arn" {
    value = "${aws_sns_topic.sns_topic.arn}"
}

output "sns_topic_policy_id" {
    value = "${aws_sns_topic_subscription.sns_topic_subscription.id}"
}

Создаем папку для полисей:

$ mkdir policies

Создаем файл с полисями:

$ vim sns_topic_delivery_policy_document.json.tpl

Прописываем:

{
  "http": {
    "defaultHealthyRetryPolicy": {
      "minDelayTarget": ${minDelayTarget},
      "maxDelayTarget": ${maxDelayTarget},
      "numRetries": ${numRetries},
      "numMaxDelayRetries": ${numMaxDelayRetries},
      "numNoDelayRetries": ${numNoDelayRetries},
      "numMinDelayRetries": ${numMinDelayRetries},
      "backoffFunction": "${backoffFunction}"
    },
    "disableSubscriptionOverrides": ${disableSubscriptionOverrides}
  }
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir sns && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region  = "us-east-1"
    # alias = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
     # access_key = "${var.aws_access_key}"
     # secret_key = "${var.aws_secret_key}"
}

module "sns" {
    source                              = "../../modules/sns"
    name                                = "TEST-SNS"
    environment                         = "PROD"

    #
    sns_protocol = "sqs"
    sns_endpoint = "arn:aws:sqs:us-east-1:316963130188:my_sqs"
}

Еще полезности:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS S3 и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с AWS SNS и Terraform в Unix/Linux» завершена.

Работа с AWS SQS и Terraform в Unix/Linux

$
0
0

Работа с AWS SQS и Terraform в Unix/Linux

Amazon Simple Queue Service (Amazon SQS) – это веб-сервис, предоставляющий доступ к очередям сообщений, в которых сообщения хранятся в ожидании обработки. С помощью Amazon SQS можно быстро создавать приложения с использованием очереди сообщений и запускать их на любом компьютере.

Amazon SQS предоставляет надежный и безопасный размещенный сервис очередей сообщений с широкими возможностями масштабирования для хранения сообщений при их передаче с одного компьютера на другой. С помощью Amazon SQS можно перемещать данные между различными компонентами распределенного приложения без потери сообщений и необходимости в постоянной доступности каждого компонента. При обмене конфиденциальными данными между приложениями можно использовать шифрование на стороне сервера Amazon SQS (SSE), интегрированное с сервисом AWS Key Management Service (KMS).

Сервис Amazon SQS позволяет создать распределенное приложение и разделить его компоненты, при этом осуществляется непосредственное взаимодействие с Amazon Elastic Compute Cloud (Amazon EC2) и другими инфраструктурными веб-сервисами AWS.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS SQS и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/sqs

Переходим в нее:

$ cd modules/sqs

Открываем файл:

$ vim sqs.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS SQS
#---------------------------------------------------
resource "aws_sqs_queue" "sqs_queue" {
    name                        = "${var.enable_fifo_queue ? "${lower(var.name)}-sqs-${lower(var.environment)}.fifo" : "${lower(var.name)}-sqs-${lower(var.environment)}" }"
    delay_seconds               = "${var.delay_seconds}"
    max_message_size            = "${var.max_message_size}"
    message_retention_seconds   = "${var.message_retention_seconds}"
    receive_wait_time_seconds   = "${var.receive_wait_time_seconds}"
    visibility_timeout_seconds  = "${var.visibility_timeout_seconds}"

    redrive_policy            = "${length(var.sqs_dead_letter_queue_arn) > 0 ? data.template_file.redrive_policy.rendered : "" }"

    fifo_queue                  = "${var.enable_fifo_queue}"
    content_based_deduplication = "${var.content_based_deduplication}"

    kms_master_key_id                 = "${var.kms_master_key_id}"
    kms_data_key_reuse_period_seconds = "${var.kms_data_key_reuse_period_seconds}"


    tags {
        Name            = "${lower(var.name)}-sqs-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }

    depends_on  = ["data.template_file.redrive_policy"]
}

data "template_file" "redrive_policy" {
    template = "${file("${path.module}/policies/redrive_policy.json.tpl")}"

    vars {
        deadLetterTargetArn = "${var.sqs_dead_letter_queue_arn}"
        maxReceiveCount     = "${var.maxReceiveCount}"
    }
}
#---------------------------------------------------
# Create AWS SQS queue policy
#---------------------------------------------------
resource "aws_sqs_queue_policy" "sqs_queue_policy" {
    queue_url   = "${aws_sqs_queue.sqs_queue.id}"
    policy      = "${data.template_file.sqs_queue_policy.rendered}"

    depends_on  = ["aws_sqs_queue.sqs_queue", "data.template_file.sqs_queue_policy"]
}

data "template_file" "sqs_queue_policy" {

    template = "${file("${path.module}/policies/sqs_queue_policy.json.tpl")}"

    vars {
        sqs_arn  = "${aws_sqs_queue.sqs_queue.arn}"
    }

}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-SQS"
}

variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}

variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}

variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}

#variable "account-id" {
#    description = "Account ID"
#    default     = ""
#}

variable "delay_seconds" {
    description = "The time in seconds that the delivery of all messages in the queue will be delayed. An integer from 0 to 900 (15 minutes). The default for this attribute is 0 seconds."
    default     = "90"
}

variable "max_message_size" {
    description = "The limit of how many bytes a message can contain before Amazon SQS rejects it. An integer from 1024 bytes (1 KiB) up to 262144 bytes (256 KiB). The default for this attribute is 262144 (256 KiB)."
    default     = "2048"
}

variable "message_retention_seconds" {
    description = "The number of seconds Amazon SQS retains a message. Integer representing seconds, from 60 (1 minute) to 1209600 (14 days). The default for this attribute is 345600 (4 days)."
    default     = "86400"
}

variable "receive_wait_time_seconds" {
    description = "The time for which a ReceiveMessage call will wait for a message to arrive (long polling) before returning. An integer from 0 to 20 (seconds). The default for this attribute is 0, meaning that the call will return immediately."
    default     = "10"
}

variable "enable_fifo_queue" {
    description = "Boolean designating a FIFO queue. If not set, it defaults to false making it standard."
    default     = "false"
}

variable "content_based_deduplication" {
    description = "Enables content-based deduplication for FIFO queues."
    default     = "false"
}

variable "kms_master_key_id" {
    description = "The ID of an AWS-managed customer master key (CMK) for Amazon SQS or a custom CMK."
    default     = "alias/aws/sqs"
}

variable "kms_data_key_reuse_period_seconds" {
    description = "The length of time, in seconds, for which Amazon SQS can reuse a data key to encrypt or decrypt messages before calling AWS KMS again. An integer representing seconds, between 60 seconds (1 minute) and 86,400 seconds (24 hours). The default is 300 (5 minutes)."
    default     = "300"
}

variable "maxReceiveCount" {
    description = "Value for redrive_policy (set maxReceiveCount for dead_letter_queue)"
    default     = "10"
}

variable "sqs_dead_letter_queue_arn" {
    description = "Set sqs arn for dead_letter_queue"
    default     = ""
}

variable "visibility_timeout_seconds" {
    description = "the timeout in seconds of visibility of the message"
    default     = 30
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "sqs_arn" {
  value = "${aws_sqs_queue.sqs_queue.arn}"
}

output "sqs_id" {
  value = "${aws_sqs_queue.sqs_queue.id}"
}

Создаем папку для полисей:

$ mkdir policies

Создаем файл с полисями:

$ vim policies/redrive_policy.json.tpl

Прописываем:

{
    "deadLetterTargetArn": "${deadLetterTargetArn}",
    "maxReceiveCount": ${maxReceiveCount}
}

И еще один файл:

Создаем файл с полисями:

$ vim policies/sqs_queue_policy.json.tpl

Прописываем:

{
  "Version": "2012-10-17",
  "Id": "sqspolicy",
  "Statement": [
    {
      "Sid": "First",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "sqs:SendMessage",
      "Resource": "${sqs_arn}",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "${sqs_arn}"
        }
      }
    }
  ]
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir sqs && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region  = "us-east-1"
    # alias = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
     # access_key = "${var.aws_access_key}"
     # secret_key = "${var.aws_secret_key}"
}

module "sqs" {
    source                              = "../../modules/sqs"
    name                                = "TEST-SQS"
    environment                         = "PROD"

    #Enable Fifo
    #enable_fifo_queue           = true
    #content_based_deduplication = true

    #sqs_dead_letter_queue_arn   = "arn:aws:sqs:us-east-1:316963130188:my_sqs"
}

Еще полезности:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS S3 и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Работа с AWS SNS и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с AWS SQS и Terraform в Unix/Linux» завершена.

Работа с AWS KMS и Terraform в Unix/Linux

$
0
0

Работа с AWS KMS и Terraform в Unix/Linux

Сервис AWS Key Management Service (KMS) – это управляемый сервис, позволяющий легко создавать ключи шифрования, используемые для шифрования данных, и управлять ими, а также использующий аппаратные модули безопасности (HSM) для защиты ключей. Сервис AWS Key Management Service (KMS) интегрирован с рядом других сервисов AWS для защиты ваших данных, которые хранятся в этих сервисах. AWS Key Management Service также интегрируется с AWS CloudTrail и предоставляет журналы использования ключевых возможностей, обеспечивая соответствие нормативным требованиям.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS KMS и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/kms

Переходим в нее:

$ cd modules/kms

Открываем файл:

$ vim kms.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS KMS key
#---------------------------------------------------
resource "aws_kms_key" "kms_key" {
    description             = "${var.description}"
    deletion_window_in_days = "${var.deletion_window_in_days}"
    key_usage               = "${var.key_usage}"

    policy                  = "${data.template_file.kms_key_policy.rendered}"
    is_enabled              = "${var.is_enabled}"
    enable_key_rotation     = "${var.enable_key_rotation}"

    tags {
        Name            = "${lower(var.name)}-kms-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }

    lifecycle {
        create_before_destroy   = true
    }

    depends_on  = ["data.template_file.kms_key_policy"]
}

data "template_file" "kms_key_policy" {
    template = "${file("${path.module}/policies/kms_key_policy.json.tpl")}"

    vars {
        admin_user  = "${var.admin_user}"
        account_id  = "${var.aws_account_id}"
    }
}
#---------------------------------------------------
# Create AWS KMS alias for kms_key
#---------------------------------------------------
resource "aws_kms_alias" "kms_alias" {
    name            = "alias/${lower(var.name)}"
    target_key_id   = "${aws_kms_key.kms_key.key_id}"

    depends_on      = ["aws_kms_key.kms_key"]
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-KMS"
}

variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}

variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}

variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}

variable "deletion_window_in_days" {
    description = "Duration in days after which the key is deleted after destruction of the resource, must be between 7 and 30 days. Defaults to 30 days."
    default     = "10"
}

variable "description" {
    description = "The description of the key as viewed in AWS console."
    default     = "This key is used to encrypt <___> AWS service"
}

variable "key_usage" {
    description = "Specifies the intended use of the key. Defaults to ENCRYPT_DECRYPT, and only symmetric encryption and decryption are supported"
    default     = ""
}

variable "is_enabled" {
    description = "Specifies whether the key is enabled. Defaults to true."
    default     = "true"
}

variable "enable_key_rotation" {
    description = "Specifies whether key rotation is enabled. Defaults to false."
    default     = "false"
}

variable "admin_user" {
    description = "Admin user in IAM"
    default     = "root"
}

variable "aws_account_id" {
    description = "AWS account ID"
    default     = ""
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "kms_key_id" {
    description = "The globally unique identifier for the key."
    value       = "${aws_kms_key.kms_key.key_id}"
}

output "kms_alias_arn" {
    value = "${aws_kms_alias.kms_alias.arn}"
}

Создаем папку для полисей:

$ mkdir policies

Создаем файл с полисями:

$ vim policies/kms_key_policy.json.tpl

Прописываем:

{
  "Version": "2012-10-17",
  "Id": "key-default-1",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::${account_id}:${admin_user}"
      },
      "Action": "kms:*",
      "Resource": "*"
    }
  ]
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir kms && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region  = "us-east-1"
    # alias = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
     # access_key = "${var.aws_access_key}"
     # secret_key = "${var.aws_secret_key}"
}

module "kms" {
    source               = "../../modules/kms"
    name                 = "TEST-KMS"
    environment          = "PROD"

    aws_account_id       = "XXXXXXXXXXXXXXXXXX"
}

Еще полезности:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS S3 и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Работа с AWS SNS и Terraform в Unix/Linux

Работа с AWS SQS и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с AWS KMS и Terraform в Unix/Linux» завершена.

Работа с AWS NLB и Terraform в Unix/Linux

$
0
0

Работа с AWS NLB и Terraform в Unix/Linux

Network Load Balancer (NLB) работает на уровне подключения (уровень 4), он маршрутизирует подключения к целевым объектам – инстансам Amazon EC2, контейнерам и IP-адресам – на основе данных IP-протокола. Network Load Balancer идеально подходит для балансировки нагрузки трафика TCP, он способен обрабатывать миллионы запросов в секунду при обеспечении сверхнизких задержек. Network Load Balancer оптимизирован для обработки резких и внезапных изменений трафика, при этом на каждую зону доступности используется один статический IP-адрес. Сервис интегрирован с другими востребованными сервисами AWS, такими как Auto Scaling, Amazon EC2 Container Service (ECS) и Amazon CloudFormation.

Балансировка нагрузки на основе подключений
Можно балансировать нагрузку трафика TCP путем маршрутизации подключений к целевым объектам – инстансам Amazon EC2, микросервисам и контейнерам, а также IP-адресам.

Высокая доступность
Network Load Balancer обеспечивает высокую доступность. Он принимает входящий трафик от клиентов и распределяет этот трафик по целевым объектам в пределах одной и той же зоны доступности. Балансировщик нагрузки также контролирует работоспособность своих зарегистрированных целевых объектов и гарантирует, что он направляет трафик только на работоспособные целевые объекты. Когда балансировщик нагрузки обнаруживает неработоспособный целевой объект, он прекращает маршрутизацию на этот целевой объект и перенаправляет трафик на оставшиеся работоспособные целевые объекты. Если в зоне доступности нет ни одного работоспособного целевого объекта, но при этом есть целевые объекты в других зонах доступности, Network Load Balancer выполнит автоматическую обработку отказа и перенаправит трафик на работоспособные целевые объекты в других зонах доступности.

Высокая пропускная способность
Network Load Balancer предназначен для обработки трафика по мере его роста и может балансировать нагрузку объемом в миллионы запросов в секунду. Он также способен обрабатывать резко и внезапно меняющийся трафик.

Низкая задержка
Network Load Balancer обеспечивает чрезвычайно низкую задержку и хорошо подходит для приложений, чувствительных к задержкам.

Сохранение IP-адреса источника
Network Load Balancer сохраняет IP-адрес источника на стороне клиента, позволяя серверу видеть IP-адрес клиента. Этот IP-адрес может затем использоваться приложениями для дальнейшей обработки.

Поддержка статического IP-адреса
Network Load Balancer автоматически предоставляет статический IP-адрес для зоны доступности (подсети), который может использоваться приложениями в качестве IP-адреса внешнего интерфейса балансировщика нагрузки.

Поддержка эластичных IP-адресов
Network Load Balancer также позволяет назначать эластичный IP-адрес для зоны доступности (подсети), тем самым предоставляя клиенту собственный фиксированный IP-адрес.

Проверки работоспособности
Network Load Balancer поддерживает проверку работоспособности целевых объектов как для сети, так и для приложений. Работоспособность на уровне сети определяется по общей реакции целевого объекта на обычный трафик. Если целевой объект не реагирует на новые соединения или реагирует слишком медленно, балансировщик нагрузки помечает целевой объект как недоступный. Проверки работоспособности на уровне приложений также могут использоваться для получения более подробной информации. Периодически опрашивая определенный URL-адрес данного целевого объекта, можно сделать обобщенный вывод о фактической работоспособности приложения. Быстрая диагностика и высокоэффективная отладка обеспечиваются полностью наглядным представлением проверок работоспособности. Причины выявленной в результате проверок неработоспособности также доступны как «коды причин» в API Network Load Balancer и через метрики Amazon CloudWatch, связанные с проверками работоспособности целевых объектов.

Обработка отказа DNS
Если в Network Load Balancer не зарегистрированы работоспособные целевые объекты или если узлы Network Load Balancer в данной зоне неработоспособны, Amazon Route 53 будет направлять трафик на узлы балансировки нагрузки в других зонах доступности.

Интеграция с Amazon Route 53
В случае отказа Network Load Balancer интеграция с Route 53 обеспечит удаление недоступных IP-адресов балансировщика нагрузки и перенаправит запросы на альтернативный балансировщик нагрузки в другом регионе.

Интеграция с сервисами AWS
Network Load Balancer интегрирован с другими сервисами AWS, такими как Auto Scaling, Amazon EC2 Container Service (ECS), AWS CloudFormation, AWS CodeDeploy и AWS Config.

Долговременные TCP-подключения
Network Load Balancer поддерживает долговременные TCP-подключения, которые идеально подходят для приложений типа WebSocket.

Централизованная поддержка API
Network Load Balancer использует тот же API, что и Application Load Balancer. Это позволяет работать с целевыми группами, проверками работоспособности и балансировать нагрузку между несколькими портами в одном инстансе Amazon EC2 для поддержки контейнерных приложений.

Надежный мониторинг и проверка
Amazon CloudWatch предоставляет метрики Network Load Balancer. CloudWatch предоставляет такие метрики, как Active Flow Count, Healthy Host Count, New Flow Count, Processed Bytes и многие другие. Network Load Balancer интегрирован с AWS CloudTrail. CloudTrail отслеживает вызовы API к Network Load Balancer.

Расширенное ведение журнала
Можно использовать возможность Flow Logs для записи всех запросов, отправленных на балансировщик нагрузки. Flow Logs регистрирует информацию об IP-трафике, поступающем на сетевые интерфейсы в VPC и из них. Данные журнала потока сохраняются с помощью Amazon CloudWatch Logs.

Изолирование по зонам
Network Load Balancer предназначен для приложений с архитектурой, размещенной в одной зоне. Если в зоне доступности что-то выходит из строя, происходит автоматическая обработка отказа и переход в другие работоспособные зоны доступности. Хотя мы рекомендуем клиентам для достижения высокой доступности настраивать балансировщик нагрузки и целевые объекты в нескольких зонах доступности, Network Load Balancer можно использовать в одной зоне доступности для поддержки архитектур, требующих изолированной работы в зоне.

Балансировка нагрузки с использованием IP-адресов как целевых объектов
Применять балансировку нагрузки можно для любого приложения, размещенного в AWS или локально, если использовать в качестве целей IP-адреса серверной части приложения. Это позволяет обеспечить балансировку нагрузки на сервер приложения, размещенный на любом IP-адресе и в любом интерфейсе инстанса. Каждое приложение, размещенное на том же инстансе, может относиться к своей группе безопасности и использовать один и тот же порт. Можно также использовать IP-адреса в качестве целей для балансировки нагрузки на приложения, размещенные локально (через подключение с помощью Direct Connect) и на инстансах EC2-Classic (с использованием ClassicLink). Возможность балансировки нагрузки между AWS и локальными ресурсами упрощает миграцию в облако, расширение ресурсов в облако или использование облака для обеспечения отказоустойчивости.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS NLB и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/nlb

Переходим в нее:

$ cd modules/nlb

Открываем файл:

$ vim nlb.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS NLB
#---------------------------------------------------
resource "aws_lb" "lb" {
    #name_prefix        = "${var.name_prefix}-"
    name                = "${lower(var.name)}-nlb-${lower(var.environment)}"
    subnets             = ["${var.subnets}"]
    internal            = "${var.lb_internal}"

    enable_deletion_protection  = "${var.enable_deletion_protection}"
    load_balancer_type          = "${var.load_balancer_type}"
    idle_timeout                = "${var.idle_timeout}"
    ip_address_type             = "${var.ip_address_type}"

    timeouts {
        create  = "${var.timeouts_create}"
        update  = "${var.timeouts_update}"
        delete  = "${var.timeouts_delete}"
    }

    lifecycle {
        create_before_destroy = true
    }

    tags {
        Name            = "${lower(var.name)}-nlb-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
}
#---------------------------------------------------
# Create AWS LB target group
#---------------------------------------------------
resource "aws_lb_target_group" "lb_target_group" {
    name                 = "${lower(var.name)}-nlb-tg-${lower(var.environment)}"
    port                 = "${var.backend_port}"
    protocol             = "${upper(var.backend_protocol)}"
    vpc_id               = "${var.vpc_id}"
    target_type          = "${var.target_type}"
    deregistration_delay = "${var.deregistration_delay}"

    tags {
        Name            = "${lower(var.name)}-nlb-tg-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }

    health_check {
        interval            = "${var.health_check_interval}"
        port                = "${var.health_check_port}"
        healthy_threshold   = "${var.health_check_healthy_threshold}"
        unhealthy_threshold = "${var.health_check_unhealthy_threshold}"
        protocol            = "${var.backend_protocol}"
    }
}
#---------------------------------------------------
# Create AWS LB listeners
#---------------------------------------------------
resource "aws_lb_listener" "frontend_tcp_80" {
    count               = "${trimspace(element(split(",", var.alb_protocols), 1)) == "TCP" ? 1 : 0}"

    load_balancer_arn   = "${aws_lb.lb.arn}"
    port                = "80"
    protocol            = "TCP"

    "default_action" {
        target_group_arn    = "${aws_lb_target_group.lb_target_group.arn}"
        type                = "forward"
    }

    depends_on = ["aws_lb.lb","aws_lb_target_group.lb_target_group"]
}
resource "aws_lb_listener" "frontend_tcp_443" {
    count               = "${trimspace(element(split(",", var.alb_protocols), 1)) == "TCP" ? 1 : 0}"

    load_balancer_arn   = "${aws_lb.lb.arn}"
    port                = "443"
    protocol            = "TCP"

    "default_action" {
        target_group_arn    = "${aws_lb_target_group.lb_target_group.arn}"
        type                = "forward"
    }

    depends_on = ["aws_lb.lb","aws_lb_target_group.lb_target_group"]
}
#---------------------------------------------------
# Create AWS LB target group attachment
#---------------------------------------------------
resource "aws_lb_target_group_attachment" "lb_target_group_attachment" {
    count               = "${length(var.target_ids) > 0 ? length(var.target_ids) : 0}"

    #availability_zone   = "all"
    target_id           = "${element(var.target_ids, count.index)}"
    port                = "${var.backend_port}"
    target_group_arn    = "${aws_lb_target_group.lb_target_group.arn}"

    depends_on = ["aws_lb_target_group.lb_target_group"]
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-NLB"
}

variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}

variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}

variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}

variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}

variable "subnets" {
    description = "A list of subnet IDs to attach to the NLB"
    type        = "list"
    default     = []
}

variable "lb_internal" {
    description = "If true, NLB will be an internal NLB"
    default     = false
}

variable "name_prefix" {
    description = "Creates a unique name beginning with the specified prefix. Conflicts with name"
    default     = "nlb"
}

variable "enable_deletion_protection" {
    description = "If true, deletion of the load balancer will be disabled via the AWS API. This will prevent Terraform from deleting the load balancer. Defaults to false."
    default     = false
}

variable "load_balancer_type" {
    description = "The type of load balancer to create. Possible values are application or network. The default value is application."
    default     = "network"
}

variable "idle_timeout" {
    description = "The time in seconds that the connection is allowed to be idle. Default: 60."
    default     = "60"
}

variable "ip_address_type" {
    description = "The type of IP addresses used by the subnets for your load balancer. The possible values are ipv4 and dualstack"
    default     = "ipv4"
}

variable "timeouts_create" {
    description = "Used for Creating LB. Default = 10mins"
    default     = "10m"
}

variable "timeouts_update" {
    description = "Used for LB modifications. Default = 10mins"
    default     = "10m"
}

variable "timeouts_delete" {
    description = "Used for LB destroying LB. Default = 10mins"
    default     = "10m"
}

variable "vpc_id" {
    description = "Set VPC ID for ?LB"
}

variable "alb_protocols" {
    description = "A protocol the ALB accepts. (e.g.: TCP)"
    default     = "TCP"
}

variable "target_type" {
    description = "The type of target that you must specify when registering targets with this target group. The possible values are instance (targets are specified by instance ID) or ip (targets are specified by IP address). The default is instance. Note that you can't specify targets for a target group using both instance IDs and IP addresses. If the target type is ip, specify IP addresses from the subnets of the virtual private cloud (VPC) for the target group, the RFC 1918 range (10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16), and the RFC 6598 range (100.64.0.0/10). You can't specify publicly routable IP addresses"
    default     = "instance"
}

variable "deregistration_delay" {
    description = "The amount time for Elastic Load Balancing to wait before changing the state of a deregistering target from draining to unused. The range is 0-3600 seconds. The default value is 300 seconds."
    default     = "300"
}

variable "backend_port" {
    description = "The port the service on the EC2 instances listen on."
    default     = 80
}

variable "backend_protocol" {
    description = "The protocol the backend service speaks. Options: HTTP, HTTPS, TCP, SSL (secure tcp)."
    default     = "HTTP"
}

variable "target_ids" {
    description = "The ID of the target. This is the Instance ID for an instance, or the container ID for an ECS container. If the target type is ip, specify an IP address."
    type        = "list"
    #default     = ""
}

variable "certificate_arn" {
    description = "The ARN of the SSL Certificate. e.g. 'arn:aws:iam::XXXXXXXXXXX:server-certificate/ProdServerCert'"
    default     = ""
}

variable "health_check_healthy_threshold" {
    description = "Number of consecutive positive health checks before a backend instance is considered healthy."
    default     = 3
}

variable "health_check_interval" {
    description = "Interval in seconds on which the health check against backend hosts is tried."
    default     = 10
}

variable "health_check_port" {
    description = "The port used by the health check if different from the traffic-port."
    default     = "traffic-port"
}

variable "health_check_unhealthy_threshold" {
    description = "Number of consecutive positive health checks before a backend instance is considered unhealthy."
    default     = 3
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "lb_name" {
    description = ""
    value       = "${aws_lb.lb.name}"
}

output "lb_arn" {
    description = "ARN of the lb itself. Useful for debug output, for example when attaching a WAF."
    value       = "${aws_lb.lb.arn}"
}

output "lb_arn_suffix" {
    description = "ARN suffix of our lb - can be used with CloudWatch"
    value       = "${aws_lb.lb.arn_suffix}"
}

output "lb_dns_name" {
    description = "The DNS name of the lb presumably to be used with a friendlier CNAME."
    value       = "${aws_lb.lb.dns_name}"
}

output "lb_id" {
    description = "The ID of the lb we created."
    value       = "${aws_lb.lb.id}"
}

output "lb_zone_id" {
    description = "The zone_id of the lb to assist with creating DNS records."
    value       = "${aws_lb.lb.zone_id}"
}

output "lb_listener_frontend_tcp_80_arn" {
    description = "The ARN of the HTTPS lb Listener we created."
    value       = "${element(concat(aws_lb_listener.frontend_tcp_80.*.arn, list("")), 0)}"
}

output "lb_listener_frontend_tcp_443_arn" {
    description = "The ARN of the HTTP lb Listener we created."
    value       = "${element(concat(aws_lb_listener.frontend_tcp_443.*.arn, list("")), 0)}"
}

output "lb_listener_frontend_tcp_80_id" {
    description = "The ID of the lb Listener we created."
    value       = "${element(concat(aws_lb_listener.frontend_tcp_80.*.id, list("")), 0)}"
}

output "lb_listener_frontend_tcp_443_id" {
    description = "The ID of the lb Listener we created."
    value       = "${element(concat(aws_lb_listener.frontend_tcp_443.*.id, list("")), 0)}"
}

output "target_group_arn" {
    description = "ARN of the target group. Useful for passing to your Auto Scaling group module."
    value       = "${aws_lb_target_group.lb_target_group.arn}"
}

 

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir nlb && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region                  = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
    profile                 = "default"
}
module "iam" {
    source                          = "../../modules/iam"
    name                            = "My-Security"
    region                          = "us-east-1"
    environment                     = "PROD"

    aws_iam_role-principals         = [
        "ec2.amazonaws.com",
    ]
    aws_iam_policy-actions           = [
        "cloudwatch:GetMetricStatistics",
        "logs:DescribeLogStreams",
        "logs:GetLogEvents",
        "elasticache:Describe*",
        "rds:Describe*",
        "rds:ListTagsForResource",
        "ec2:DescribeAccountAttributes",
        "ec2:DescribeAvailabilityZones",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeVpcs",
        "ec2:Owner",
    ]
}
module "vpc" {
    source                              = "../../modules/vpc"
    name                                = "My"
    environment                         = "PROD"
    # VPC
    instance_tenancy                    = "default"
    enable_dns_support                  = "true"
    enable_dns_hostnames                = "true"
    assign_generated_ipv6_cidr_block    = "false"
    enable_classiclink                  = "false"
    vpc_cidr                            = "172.31.0.0/16"
    private_subnet_cidrs                = ["172.31.32.0/20"]
    public_subnet_cidrs                 = ["172.31.0.0/20"]
    availability_zones                  = ["us-east-1b"]
    enable_all_egress_ports             = "true"
    allowed_ports                       = ["8080", "3306", "443", "80"]

    map_public_ip_on_launch             = "true"

    #Internet-GateWay
    enable_internet_gateway             = "true"
    #NAT
    enable_nat_gateway                  = "false"
    single_nat_gateway                  = "true"
    #VPN
    enable_vpn_gateway                  = "false"
    #DHCP
    enable_dhcp_options                 = "false"
    # EIP
    enable_eip                          = "false"
}
module "ec2" {
    source                              = "../../modules/ec2"
    name                                = "TEST-Machine"
    region                              = "us-east-1"
    environment                         = "PROD"
    number_of_instances                 = 2
    ec2_instance_type                   = "t2.micro"
    enable_associate_public_ip_address  = "true"
    disk_size                           = "8"
    tenancy                             = "${module.vpc.instance_tenancy}"
    iam_instance_profile                = "${module.iam.instance_profile_id}"
    subnet_id                           = "${element(module.vpc.vpc-publicsubnet-ids, 0)}"
    #subnet_id                           = "${element(module.vpc.vpc-privatesubnet-ids, 0)}"
    #subnet_id                           = ["${element(module.vpc.vpc-privatesubnet-ids)}"]
    vpc_security_group_ids              = ["${module.vpc.security_group_id}"]

    monitoring                          = "true"
}
module "nlb" {
    source                  = "../../modules/nlb"
    name                    = "Load-Balancer"
    region                  = "us-east-1"
    environment             = "PROD"

    subnets                     = ["${module.vpc.vpc-privatesubnet-ids}"]
    vpc_id                      = "${module.vpc.vpc_id}"
    enable_deletion_protection  = false

    backend_protocol    = "TCP"
    alb_protocols       = "TCP"

    target_ids          = ["${module.ec2.instance_ids}"]
}

Еще полезности:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS S3 и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Работа с AWS SNS и Terraform в Unix/Linux

Работа с AWS SQS и Terraform в Unix/Linux

Работа с AWS KMS и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с AWS NLB и Terraform в Unix/Linux» завершена.


Работа с AWS CloudWatch и Terraform в Unix/Linux

$
0
0

Работа с AWS CloudWatch и Terraform в Unix/Linux

Amazon CloudWatch – это сервис мониторинга облачных ресурсов AWS и приложений, которые вы запускаете с их помощью. Amazon CloudWatch можно использовать для сбора и отслеживания метрик, накопления и анализа файлов журналов, создания предупреждений, а также автоматического реагирования на изменения ресурсов AWS. Amazon CloudWatch может использоваться для мониторинга следующих ресурсов AWS: инстансов Amazon EC2, таблиц Amazon DynamoDB, инстансов Amazon RDS DB, а также для мониторинга пользовательских метрик приложений и сервисов и любых логов ваших приложений. Можно использовать Amazon CloudWatch для получения сводной информации о системе, включающей в себя информацию об используемых ресурсах, производительности приложений и общем состоянии системы. Эти данные применяются для оперативного реагирования и обеспечения стабильной работы приложений.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS CloudWatch и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/cloudwatch

Переходим в нее:

$ cd modules/cloudwatch

Открываем файл:

$ vim cloudwatch.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS CloudWatch metric alarm
#---------------------------------------------------
resource "aws_cloudwatch_metric_alarm" "cw_metric_alarm" {
    count               = "${var.alarm_name != "" ? 1 : 0}"

    alarm_name          = "${var.alarm_name}"
    comparison_operator = "${var.comparison_operator}"
    evaluation_periods  = "${var.evaluation_periods}"
    metric_name         = "${var.metric_name}"
    namespace           = "${var.namespace}"
    period              = "${var.period}"
    threshold           = "${var.threshold}"

    datapoints_to_alarm = "${var.datapoints_to_alarm}"
    actions_enabled     = "${var.actions_enabled}"
    dimensions          = "${var.dimensions}"

    alarm_description = "${var.alarm_description}"
    alarm_actions     = ["${var.alarm_actions}"]

    insufficient_data_actions   = "${var.insufficient_data_actions}"
    ok_actions                  = "${var.ok_actions}"

    #extended_statistic                      = "${var.extended_statistic}"
    #evaluate_low_sample_count_percentiles   = "${var.evaluate_low_sample_count_percentiles}"
    statistic                               = "${var.statistic}"
    treat_missing_data                      = "${var.treat_missing_data}"
}
#---------------------------------------------------
# Create AWS CloudWatch event permission
#---------------------------------------------------
resource "aws_cloudwatch_event_permission" "cw_event_permission" {
    count       = "${var.principal_for_event_permission != "" ? 1 : 0}"

    principal    = "${var.principal_for_event_permission}"
    statement_id = "${var.statement_id_for_event_permission}"
    action      = "${var.action_for_event_permission}"
}
#---------------------------------------------------
# Create AWS CloudWatch event rule
#---------------------------------------------------
resource "aws_cloudwatch_event_rule" "cw_event_rule" {
    count       = "${var.arn_for_cloudwatch_event_target != "" ? 1 : 0}"
    name        = "capture-aws-sign-in"
    description = "Capture each AWS Console Sign In"

    event_pattern = <<PATTERN
        {
            "detail-type": [
                "AWS Console Sign In via CloudTrail"
            ]
        }
    PATTERN
    is_enabled  = "${var.is_enabled_for_event_rule}"
}

resource "aws_cloudwatch_event_target" "cloudwatch_event_target" {
    count   = "${var.arn_for_cloudwatch_event_target != "" ? 1 : 0}"

    rule      = "${aws_cloudwatch_event_rule.cw_event_rule.name}"
    target_id = "${var.target_id_for_cloudwatch_event_target}"
    arn       = "${var.arn_for_cloudwatch_event_target}"
}
#---------------------------------------------------
# Create AWS CloudWatch Create AWS dashboard
#---------------------------------------------------
resource "aws_cloudwatch_dashboard" "cloudwatch_dashboard" {
    count           = "${var.cloudwatch_dashboard_name !="" ? 1 : 0}"

    dashboard_name  = "${var.cloudwatch_dashboard_name}"
    dashboard_body  = <<EOF
 {
   "widgets": [
       {
          "type":"metric",
          "x":0,
          "y":0,
          "width":12,
          "height":6,
          "properties":{
             "metrics":[
                [
                   "AWS/EC2",
                   "CPUUtilization",
                   "InstanceId",
                   "i-012345"
                ]
             ],
             "period":300,
             "stat":"Average",
             "region":"us-east-1",
             "title":"EC2 Instance CPU"
          }
       },
       {
          "type":"text",
          "x":0,
          "y":7,
          "width":3,
          "height":3,
          "properties":{
             "markdown":"Hello world"
          }
       }
   ]
 }
 EOF
}
#---------------------------------------------------
# Create AWS CloudWatch LOG group
#---------------------------------------------------
resource "aws_cloudwatch_log_group" "cw_log_group" {
    count               = "${var.name_for_cloudwatch_log_group !="" ? 1 : 0}"

    name                = "${var.name_for_cloudwatch_log_group}"
    retention_in_days   = "${var.retention_in_days_for_cloudwatch_log_group}"
    kms_key_id          = "${var.kms_key_id_for_cloudwatch_log_group}"


    tags {
        Name            = "${var.name}-cw-log-group-${var.environment}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
}
#---------------------------------------------------
# Create AWS CloudWatch LOG metric filter
#---------------------------------------------------
resource "aws_cloudwatch_log_metric_filter" "cloudwatch_log_metric_filter" {
    count          = "${var.name_for_cloudwatch_log_group !="" ? 1 : 0}"

    name           = "${var.name_for_cloudwatch_log_metric_filter}"
    pattern        = "${var.pattern_for_cloudwatch_log_metric_filter}"
    log_group_name = "${aws_cloudwatch_log_group.cw_log_group.name}"

    metric_transformation {
        name      = "${var.name_for_metric_transformation}"
        namespace = "${var.namespace_for_metric_transformation}"
        value     = "${var.value_for_metric_transformation}"
    }
}
#---------------------------------------------------
# Create AWS CloudWatch LOG stream
#---------------------------------------------------
resource "aws_cloudwatch_log_stream" "cloudwatch_log_stream" {
    count          = "${var.name_for_cloudwatch_log_stream !="" ? 1 : 0}"

    name           = "${var.name_for_cloudwatch_log_stream}"
    log_group_name = "${aws_cloudwatch_log_group.cw_log_group.name}"
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-RDS"
}

variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}

variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}

variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}

variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}

variable "alarm_name" {
  description = "The descriptive name for the alarm. This name must be unique within the user's AWS account"
  default     = ""
}

variable "comparison_operator" {
  description = "The arithmetic operation to use when comparing the specified Statistic and Threshold. The specified Statistic value is used as the first operand. Either of the following is supported: GreaterThanOrEqualToThreshold, GreaterThanThreshold, LessThanThreshold, LessThanOrEqualToThreshold."
  default     = "GreaterThanOrEqualToThreshold"
}

variable "evaluation_periods" {
    description = "The number of periods over which data is compared to the specified threshold."
    default     = "2"
}

variable "metric_name" {
    description = "The name for the alarm's associated metric (ex: CPUUtilization)"
    default     = "CPUUtilization"
}

variable "namespace" {
    description = "The namespace for the alarm's associated metric (ex: AWS/EC2)"
    default     = "AWS/EC2"
}

variable "period" {
    description = "The period in seconds over which the specified statistic is applied."
    default     = "120"
}

variable "statistic" {
    description = "The statistic to apply to the alarm's associated metric. Either of the following is supported: SampleCount, Average, Sum, Minimum, Maximum"
    default     = "Average"
}

variable "threshold" {
    description = "The value against which the specified statistic is compared"
    default     = "80"
}

variable "actions_enabled" {
    description = "Indicates whether or not actions should be executed during any changes to the alarm's state. Defaults to true."
    default     = "true"
}

variable "alarm_actions" {
    description = "The list of actions to execute when this alarm transitions into an ALARM state from any other state. Each action is specified as an Amazon Resource Number (ARN)."
    type        = "list"
    default     = []
}

variable "alarm_description" {
    description = "The description for the alarm."
    default     = ""
}

variable "datapoints_to_alarm" {
    description = "The number of datapoints that must be breaching to trigger the alarm."
    default     = "0"
}

variable "dimensions" {
    description = "List of the dimensions for the alarm's associated metric"
    type        = "list"
    default     = []
}

variable "insufficient_data_actions" {
    description = "The list of actions to execute when this alarm transitions into an INSUFFICIENT_DATA state from any other state. Each action is specified as an Amazon Resource Number (ARN)."
    type        = "list"
    default     = []
}

variable "ok_actions" {
    description = "The list of actions to execute when this alarm transitions into an OK state from any other state. Each action is specified as an Amazon Resource Number (ARN)."
    type        = "list"
    default     = []
}

variable "unit" {
    description = "The unit for the alarm's associated metric."
    default     = ""
}

variable "extended_statistic" {
    description = "The percentile statistic for the metric associated with the alarm. Specify a value between p0.0 and p100."
    default     = "p100"
}

variable "treat_missing_data" {
    description = "Sets how this alarm is to handle missing data points. The following values are supported: missing, ignore, breaching and notBreaching. Defaults to missing."
    default     = "missing"
}

variable "evaluate_low_sample_count_percentiles" {
    description = "Used only for alarms based on percentiles. If you specify ignore, the alarm state will not change during periods with too few data points to be statistically significant. If you specify evaluate or omit this parameter, the alarm will always be evaluated and possibly change state no matter how many data points are available. The following values are supported: ignore, and evaluate."
    default     = "ignore"
}

variable "principal_for_event_permission" {
    description = "The 12-digit AWS account ID that you are permitting to put events to your default event bus. Specify * to permit any account to put events to your default event bus."
    default     = ""
}

variable "statement_id_for_event_permission" {
    description = "An identifier string for the external account that you are granting permissions to."
    default     = "DevAccountAccess"
}

variable "action_for_event_permission" {
    description = "The action that you are enabling the other account to perform. Defaults to events:PutEvents."
    default     = "events:PutEvents"
}

variable "is_enabled_for_event_rule" {
    description = "Whether the rule should be enabled (defaults to true)."
    default     = "true"
}

variable "arn_for_cloudwatch_event_target" {
    description = "The Amazon Resource Name (ARN) of the rule."
    default     = ""
}

variable "target_id_for_cloudwatch_event_target" {
    description = "target ID"
    default     = "SendToSNS"
}

variable "cloudwatch_dashboard_name" {
    description = "The name of the dashboard."
    default     = ""
}
variable "name_for_cloudwatch_log_group" {
    description = "The name of the log group. If omitted, Terraform will assign a random, unique name."
    default     = ""
}

variable "retention_in_days_for_cloudwatch_log_group" {
    description = "Specifies the number of days you want to retain log events in the specified log group."
    default     = "0"
}

variable "kms_key_id_for_cloudwatch_log_group" {
    description = "The ARN of the KMS Key to use when encrypting log data. Please note, after the AWS KMS CMK is disassociated from the log group, AWS CloudWatch Logs stops encrypting newly ingested data for the log group. All previously ingested data remains encrypted, and AWS CloudWatch Logs requires permissions for the CMK whenever the encrypted data is requested."
    default     = ""
}

variable "name_for_cloudwatch_log_metric_filter" {
    description = "A name for the metric filter."
    default     = "metric-filter"
}

variable "pattern_for_cloudwatch_log_metric_filter" {
    description = "A valid CloudWatch Logs filter pattern for extracting metric data out of ingested log events."
    default     = ""
}

variable "name_for_metric_transformation" {
    description = "The name of the CloudWatch metric to which the monitored log information should be published (e.g. ErrorCount)"
    default     = "ErrorCount"
}

variable "namespace_for_metric_transformation" {
    description = "The destination namespace of the CloudWatch metric."
    default     = "NameSpace"
}

variable "value_for_metric_transformation" {
    description = "What to publish to the metric. For example, if you're counting the occurrences of a particular term like 'Error', the value will be '1' for each occurrence. If you're counting the bytes transferred the published value will be the value in the log event."
    default     = "1"
}

variable "name_for_cloudwatch_log_stream" {
    description = "The name of the log stream. Must not be longer than 512 characters and must not contain :"
    default     = ""
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "cw_metric_alarm_ids" {
    description = ""
    value       = "${aws_cloudwatch_metric_alarm.cw_metric_alarm.*.id}"
}

output "cw_event_permission_ids" {
    description = ""
    value       = "${aws_cloudwatch_event_permission.cw_event_permission.*.id}"
}

output "cw_event_rule_ids" {
    description = ""
    value       = "${aws_cloudwatch_event_rule.cw_event_rule.*.id}"
}

output "cw_event_rule_names" {
    description = ""
    value       = "${aws_cloudwatch_event_rule.cw_event_rule.*.name}"
}

output "cloudwatch_dashboard_ids" {
    description = ""
    value       = "${aws_cloudwatch_dashboard.cloudwatch_dashboard.*.id}"
}

output "cloudwatch_dashboard_names" {
    description = ""
    value       = "${aws_cloudwatch_dashboard.cloudwatch_dashboard.*.name}"
}

output "cw_log_group_ids" {
    description = ""
    value       = "${aws_cloudwatch_log_group.cw_log_group.*.id}"
}

output "cw_log_group_names" {
    description = ""
    value       = "${aws_cloudwatch_log_group.cw_log_group.*.name}"
}

output "cloudwatch_log_metric_filter_ids" {
    description = ""
    value       = "${aws_cloudwatch_log_metric_filter.cloudwatch_log_metric_filter.*.ids}"
}

output "cloudwatch_log_metric_filter_names" {
    description = ""
    value       = "${aws_cloudwatch_log_metric_filter.cloudwatch_log_metric_filter.*.names}"
}

output "cloudwatch_log_stream_ids" {
    description = ""
    value       = "${aws_cloudwatch_log_stream.cloudwatch_log_stream.*.id}"
}

output "cloudwatch_log_stream_names" {
    description = ""
    value       = "${aws_cloudwatch_log_stream.cloudwatch_log_stream.*.name}"
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir cloudwatch && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region  = "us-east-1"
    profile = "default"
}
module "cloudwatch" {
    source                  = "../../modules/cloudwatch"

    dimensions = [
        {
          AutoScalingGroupName = ""
          #AutoScalingGroupName = "${aws_autoscaling_group.bar.name}"
        }
    ]

    alarm_name          = "My first alarm"
    #alarm_description  = "Test description"
    #alarm_actions      = "${aws_autoscaling_policy.bat.arn}"

    #
    #principal_for_event_permission  = "XXXXXXXXXXXXXXX"

    #arn_for_cloudwatch_event_target = "arn:aws:sns:us-east-1:XXXXXXXXXXXXXXX:test-sns-sns-prod"
    #
    #name_for_cloudwatch_log_group   = "test-log-group"
    #
    #name_for_cloudwatch_log_stream  = "test-log-steam"
}

Еще полезности:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS S3 и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Работа с AWS SNS и Terraform в Unix/Linux

Работа с AWS SQS и Terraform в Unix/Linux

Работа с AWS KMS и Terraform в Unix/Linux

Работа с AWS NLB и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с AWS CloudWatch и Terraform в Unix/Linux» завершена.

Работа с AWS ALB и Terraform в Unix/Linux

$
0
0

Работа с AWS ALB и Terraform в Unix/Linux

Application Load Balancer работает на уровне запросов (уровень 7), маршрутизируя трафик на целевые объекты – инстансы EC2, контейнеры и IP-адреса – на основе содержимого запроса. Application Load Balancer идеально подходит для расширенной балансировки нагрузки HTTP и HTTPS-трафика. Он обеспечивает расширенную маршрутизацию запросов, ориентированную на доставку приложений, построенных на базе современных архитектур, включая микросервисы и приложения на основе контейнеров. Application Load Balancer упрощает настройку и повышает безопасность приложения, гарантируя, что всегда используются самые новые версии шифров и протоколов SSL/TLS.

Балансировка нагрузки на уровне 7
Имеется возможность осуществлять балансировку нагрузки приложений, использующих протокол HTTP/HTTPS, и использовать особые возможности уровня 7, такие как заголовки X-Forwarded-For.

Поддержка HTTPS
Application Load Balancer поддерживает использование HTTPS-терминации между клиентами и балансировщиком нагрузки. Application Load Balancer также позволяет управлять SSL-сертификатами с помощью AWS Identity and Access Management (IAM) и AWS Certificate Manager для предустановленных политик безопасности.

Server Name Indication (SNI)
Server Name Indication (SNI) – это расширение протокола TLS, с помощью которого клиент обозначает имя узла для подключения в начале установления связи по протоколу TLS. Балансировщик нагрузки может передавать через один и тот же обработчик событий безопасности несколько сертификатов, благодаря чему он способен поддерживать несколько защищенных веб-сайтов через один обработчик событий безопасности. Балансировщики нагрузки приложений также поддерживают интеллектуальный алгоритм выбора сертификатов при работе с SNI. Если имя узла, обозначенное клиентом, соответствует нескольким сертификатам, балансировщик нагрузки определяет наилучший сертификат на основании ряда факторов, в том числе учитывая возможности клиента.

IP-адреса как цели
Применять балансировку нагрузки можно для любого приложения, размещенного в AWS или локально, если использовать в качестве целей IP-адреса серверной части приложения. Это позволяет обеспечить балансировку нагрузки на сервер приложения, размещенный на любом IP-адресе и в любом интерфейсе инстанса. Каждое приложение, размещенное на том же инстансе, может относиться к своей группе безопасности и использовать один и тот же порт. Можно также использовать IP-адреса в качестве целей для приложений с балансировкой нагрузки, размещенных локально (через подключение с помощью Direct Connect или VPN-соединения), в VPC с пиринговым подключением или на инстансах EC2-Classic (с использованием ClassicLink). Возможность балансировки нагрузки между AWS и локальными ресурсами упрощает миграцию в облако, расширение ресурсов в облако или использование облака для обеспечения отказоустойчивости.

Высокая доступность
Для Application Load Balancer необходимо указать более одной зоны доступности. Можно распределять входящий трафик по объектам в нескольких зонах доступности. Application Load Balancer автоматически масштабирует ресурсы, необходимые для обработки запросов, реагируя на входящий трафик приложений.

Возможности обеспечения безопасности
При использовании облака Amazon Virtual Private Cloud (Amazon VPC) можно создать группы безопасности, связанные с Elastic Load Balancing, и управлять ими, чтобы обеспечить дополнительные варианты использования сетевой конфигурации и настройки безопасности. Можно настроить Application Load Balancer для работы с выходом в Интернет или создать балансировщик нагрузки без публичного IP-адреса для работы в качестве внутреннего балансировщика нагрузки (без выхода в Интернет).

Маршрутизация на основе контента
Если приложение состоит из нескольких отдельных сервисов, Application Load Balancer может направлять запрос в определенный сервис на основе содержания запроса.

Маршрутизация на основе узла
Можно выполнять маршрутизацию запросов клиента в зависимости от поля Host HTTP-заголовка – это позволяет из одного и того же балансировщика нагрузки осуществлять маршрутизацию в несколько доменов.

Маршрутизация на основе пути
Можно выполнять маршрутизацию запросов на основе URL-адреса заголовка HTTP.

Поддержка приложений на основе контейнеров
Application Load Balancer обеспечивает расширенную поддержку контейнеров путем балансировки нагрузки между несколькими портами в одном инстансе Amazon EC2. Глубокая интеграция с Amazon EC2 Container Service (ECS) обеспечивает полностью управляемое контейнерное предложение. ECS позволяет в определении задания ECS указать динамический порт, в этом случае контейнеру, запланированному для инстанса EC2, будет передан неиспользуемый порт. Планировщик ECS автоматически добавляет задание в балансировщик нагрузки, используя этот порт.

Поддержка HTTP/2
HTTP/2 – это новая версия протокола передачи гипертекста (HTTP), который использует единое мультиплексное соединение, позволяющее обеспечить отправку нескольких запросов по одному соединению. Он также осуществляет сжатие данных заголовка перед его отправкой в двоичном формате, а также поддерживает установку TLS-соединения с клиентами.

Поддержка WebSocket
WebSocket позволяет серверу в режиме реального времени обмениваться сообщениями с конечными пользователями без необходимости конечных пользователей запрашивать (или опрашивать) этот сервер на наличие обновлений. Протокол WebSocket обеспечивает двунаправленные каналы связи между клиентом и сервером в установленном длительное время TCP-соединении.

Встроенная поддержка протокола IPv6
Application Load Balancer поддерживает работу по интернет-протоколу версии 6 (IPv6) в облаке VPC. Это позволяет клиентам подключаться к Application Load Balancer по протоколам IPv4 или IPv6.

Закрепленные сеансы
Закрепленные сеансы – это механизм маршрутизации запросов из одного и того же клиента к одному и тому же получателю. Application Load Balancer поддерживает закрепленные сеансы с помощью файлов cookie, сгенерированных балансировщиком нагрузки. Если включить закрепленные сеансы, то тот же получатель будет получать запрос и сможет использовать файлы cookie для восстановления контекста сеанса. Закрепленность определяется на уровне целевой группы.

Проверки работоспособности
Application Load Balancer направляет трафик только к работоспособным объектам. С помощью Application Load Balancer можно двумя способами добиться оптимального представления о работоспособности своих приложений. 1) Путем расширенной проверки работоспособности, которая позволяет настроить подробные коды ошибок с 200 по 499. Проверка работоспособности позволяет следить за состоянием каждого из сервисов под управлением балансировщика нагрузки. 2) С помощью новых метрик, которые дают представление о трафике для каждого из сервисов, работающих на инстансе EC2.

Мониторинг в процессе работы
В отчетах Amazon CloudWatch присутствует информация о таких метриках Application Load Balancer, как количество запросов, количество ошибок, тип ошибок и время задержки.

Ведение журналов
Можно использовать возможность ведения журналов доступа для записи всех запросов, отправленных балансировщику нагрузки, и сохранять файлы журналов в Amazon S3 для последующего анализа. Файлы журналов сжаты и имеют расширение .gzip. Сжатые файлы журналов экономят дисковое пространство и пропускную способность при передаче данных и могут использоваться для диагностики сбоев приложений и анализа сетевого трафика.

Можно также использовать AWS CloudTrail для записи вызовов API Application Load Balancer в аккаунте и доставки файлов журналов. История вызовов API позволяет выполнять анализ безопасности, отслеживать изменения ресурсов и аудит соответствия.

Защита от удаления
Можно включить для Application Load Balancer защиту от удаления, чтобы предотвратить возможность его случайного удаления.

Отслеживание запросов
Application Load Balancer вставляет новый пользовательский идентификатор «X-Amzn-Trace-Id» HTTP-заголовка для всех запросов, поступающих в балансировщик нагрузки. Возможность отслеживания запросов позволяет отслеживать запрос по его уникальному ID, поскольку запрос проходит свой путь через различные сервисы, которые являются составляющими ваших веб-сайтов и распределенных приложений. Уникальный идентификатор отслеживания можно использовать для того, чтобы выявить любые проблемы с производительностью или синхронизацией в стеке приложения с детализацией на уровне отдельного запроса.

Web Application Firewall
Теперь можно использовать AWS WAF для защиты интернет-приложений на своих балансировщиках Application Load Balancer. AWS WAF – это брандмауэр для интернет-приложений, который позволяет защитить их от распространенных сетевых эксплойтов, способных повлиять на доступность приложения, создать угрозу безопасности или задействовать чрезмерное количество ресурсов.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS ALB и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/alb

Переходим в нее:

$ cd modules/alb

Открываем файл:

$ vim alb.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS ALB
#---------------------------------------------------
resource "aws_lb" "alb" {
    #name_prefix        = "${var.name_prefix}-"
    name                = "${lower(var.name)}-alb-${lower(var.environment)}"
    security_groups     = ["${var.security_groups}"]
    subnets             = ["${var.subnets}"]
    internal            = "${var.lb_internal}"

    enable_deletion_protection  = "${var.enable_deletion_protection}"
    load_balancer_type          = "${var.load_balancer_type}"
    idle_timeout                = "${var.idle_timeout}"
    ip_address_type             = "${var.ip_address_type}"

    access_logs         = ["${var.access_logs}"]

    timeouts {
        create  = "${var.timeouts_create}"
        update  = "${var.timeouts_update}"
        delete  = "${var.timeouts_delete}"
    }

    lifecycle {
        create_before_destroy = true
    }

    tags {
        Name            = "${lower(var.name)}-alb-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
}
#---------------------------------------------------
# Create AWS LB target group
#---------------------------------------------------
resource "aws_lb_target_group" "alb_target_group" {
    name                 = "${lower(var.name)}-alb-tg-${lower(var.environment)}"
    port                 = "${var.backend_port}"
    protocol             = "${upper(var.backend_protocol)}"
    vpc_id               = "${var.vpc_id}"
    target_type          = "${var.target_type}"
    deregistration_delay = "${var.deregistration_delay}"

    tags {
        Name            = "${lower(var.name)}-alb-tg-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }

    health_check {
        interval            = "${var.health_check_interval}"
        path                = "${var.health_check_path}"
        port                = "${var.health_check_port}"
        healthy_threshold   = "${var.health_check_healthy_threshold}"
        unhealthy_threshold = "${var.health_check_unhealthy_threshold}"
        timeout             = "${var.health_check_timeout}"
        protocol            = "${var.backend_protocol}"
        matcher             = "${var.health_check_matcher}"
    }
    stickiness {
        type            = "lb_cookie"
        cookie_duration = "${var.cookie_duration}"
        enabled         = "${var.cookie_duration != 1 ? true : false}"
    }
}
#---------------------------------------------------
# Create AWS LB listeners
#---------------------------------------------------
resource "aws_lb_listener" "frontend_http" {
    count               = "${trimspace(element(split(",", var.alb_protocols), 1)) == "HTTP" || trimspace(element(split(",", var.alb_protocols), 2)) == "HTTP" ? 1 : 0}"

    load_balancer_arn   = "${aws_lb.alb.arn}"
    port                = "80"
    protocol            = "HTTP"

    "default_action" {
        target_group_arn    = "${aws_lb_target_group.alb_target_group.arn}"
        type                = "forward"
    }

    depends_on = ["aws_lb.alb","aws_lb_target_group.alb_target_group"]
}

resource "aws_lb_listener" "frontend_https" {
    count               = "${trimspace(element(split(",", var.alb_protocols), 1)) == "HTTPS" || trimspace(element(split(",", var.alb_protocols), 2)) == "HTTPS" ? 1 : 0}"

    load_balancer_arn   = "${aws_lb.alb.arn}"
    port                = 443
    protocol            = "HTTPS"
    certificate_arn     = "${var.certificate_arn}"
    ssl_policy          = "ELBSecurityPolicy-2016-08"
    default_action {
        target_group_arn    = "${aws_lb_target_group.alb_target_group.arn}"
        type                = "forward"
    }

    depends_on = ["aws_lb.alb","aws_lb_target_group.alb_target_group"]
}
#---------------------------------------------------
# Create AWS LB target group attachment
#---------------------------------------------------
resource "aws_lb_target_group_attachment" "alb_target_group_attachment" {
    #count               = "${length(var.target_ids)}"

    #availability_zone   = "all"
    target_group_arn    = "${aws_lb_target_group.alb_target_group.arn}"
    target_id           = "${element(var.target_ids, 0)}"
    #target_id           = "${element(var.target_ids, count.index)}"
    #target_id           = "${var.target_ids[count.index]}"
    port                = "${var.backend_port}"

    depends_on = ["aws_lb.alb","aws_lb_target_group.alb_target_group"]
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-ALB"
}

variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}

variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}

variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}

variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}

variable "security_groups" {
    description = "A list of security group IDs to assign to the ELB. Only valid if creating an ELB within a VPC"
    type        = "list"
}

variable "subnets" {
    description = "A list of subnet IDs to attach to the ELB"
    type        = "list"
    default     = []
}

variable "lb_internal" {
    description = "If true, ALB will be an internal ALB"
    default     = false
}

variable "name_prefix" {
    description = "Creates a unique name beginning with the specified prefix. Conflicts with name"
    default     = "alb"
}

variable "enable_deletion_protection" {
    description = "If true, deletion of the load balancer will be disabled via the AWS API. This will prevent Terraform from deleting the load balancer. Defaults to false."
    default     = false
}

# Access logs
variable "access_logs" {
    description = "An access logs block. Uploads access logs to S3 bucket. Can be used just for network LB!"
    type        = "list"
    default     = []
}

variable "load_balancer_type" {
    description = "The type of load balancer to create. Possible values are application or network. The default value is application."
    default     = "application"
}

variable "idle_timeout" {
    description = "The time in seconds that the connection is allowed to be idle. Default: 60."
    default     = "60"
}

variable "ip_address_type" {
    description = "The type of IP addresses used by the subnets for your load balancer. The possible values are ipv4 and dualstack"
    default     = "ipv4"
}

variable "timeouts_create" {
    description = "Used for Creating LB. Default = 10mins"
    default     = "10m"
}

variable "timeouts_update" {
    description = "Used for LB modifications. Default = 10mins"
    default     = "10m"
}

variable "timeouts_delete" {
    description = "Used for LB destroying LB. Default = 10mins"
    default     = "10m"
}

variable "vpc_id" {
    description = "Set VPC ID for ?LB"
}

variable "alb_protocols" {
    description = "A comma delimited list of the protocols the ALB accepts. e.g.: HTTPS"
    default     = "HTTP,HTTPS"
}

variable "target_type" {
    description = "The type of target that you must specify when registering targets with this target group. The possible values are instance (targets are specified by instance ID) or ip (targets are specified by IP address). The default is instance. Note that you can't specify targets for a target group using both instance IDs and IP addresses. If the target type is ip, specify IP addresses from the subnets of the virtual private cloud (VPC) for the target group, the RFC 1918 range (10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16), and the RFC 6598 range (100.64.0.0/10). You can't specify publicly routable IP addresses"
    default     = "instance"
}

variable "deregistration_delay" {
    description = "The amount time for Elastic Load Balancing to wait before changing the state of a deregistering target from draining to unused. The range is 0-3600 seconds. The default value is 300 seconds."
    default     = "300"
}

variable "backend_port" {
    description = "The port the service on the EC2 instances listen on."
    default     = 80
}

variable "backend_protocol" {
    description = "The protocol the backend service speaks. Options: HTTP, HTTPS, TCP, SSL (secure tcp)."
    default     = "HTTP"
}

variable "target_ids" {
    description = "The ID of the target. This is the Instance ID for an instance, or the container ID for an ECS container. If the target type is ip, specify an IP address."
    type        = "list"
    #default     = []
}

variable "certificate_arn" {
    description = "The ARN of the SSL Certificate. e.g. 'arn:aws:iam::XXXXXXXXXXX:server-certificate/ProdServerCert'"
    default     = ""
}

variable "health_check_healthy_threshold" {
    description = "Number of consecutive positive health checks before a backend instance is considered healthy."
    default     = 3
}

variable "health_check_interval" {
    description = "Interval in seconds on which the health check against backend hosts is tried."
    default     = 10
}

variable "health_check_path" {
    description = "The URL the ELB should use for health checks. e.g. /health"
    default     = "/"
}

variable "health_check_port" {
    description = "The port used by the health check if different from the traffic-port."
    default     = "traffic-port"
}

variable "health_check_timeout" {
    description = "Seconds to leave a health check waiting before terminating it and calling the check unhealthy."
    default     = 5
}

variable "health_check_unhealthy_threshold" {
    description = "Number of consecutive positive health checks before a backend instance is considered unhealthy."
    default     = 3
}

variable "health_check_matcher" {
    description = "The HTTP codes that are a success when checking TG health."
    default     = "200-299"
}

variable "cookie_duration" {
    description = "If load balancer connection stickiness is desired, set this to the duration in seconds that cookie should be valid (e.g. 300). Otherwise, if no stickiness is desired, leave the default."
    default     = 1
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "lb_name" {
    description = ""
    value       = "${aws_lb.alb.name}"
}

output "lb_arn" {
    description = "ARN of the lb itself. Useful for debug output, for example when attaching a WAF."
    value       = "${aws_lb.alb.arn}"
}

output "lb_arn_suffix" {
    description = "ARN suffix of our lb - can be used with CloudWatch"
    value       = "${aws_lb.alb.arn_suffix}"
}

output "lb_dns_name" {
    description = "The DNS name of the lb presumably to be used with a friendlier CNAME."
    value       = "${aws_lb.alb.dns_name}"
}

output "lb_id" {
    description = "The ID of the lb we created."
    value       = "${aws_lb.alb.id}"
}

output "lb_zone_id" {
    description = "The zone_id of the lb to assist with creating DNS records."
    value       = "${aws_lb.alb.zone_id}"
}

output "lb_listener_https_arn" {
    description = "The ARN of the HTTPS lb Listener we created."
    value       = "${element(concat(aws_lb_listener.frontend_https.*.arn, list("")), 0)}"
}

output "lb_listener_http_arn" {
    description = "The ARN of the HTTP lb Listener we created."
    value       = "${element(concat(aws_lb_listener.frontend_http.*.arn, list("")), 0)}"
}

output "lb_listener_https_id" {
    description = "The ID of the lb Listener we created."
    value       = "${element(concat(aws_lb_listener.frontend_https.*.id, list("")), 0)}"
}

output "lb_listener_http_id" {
    description = "The ID of the lb Listener we created."
    value       = "${element(concat(aws_lb_listener.frontend_http.*.id, list("")), 0)}"
}

output "target_group_arn" {
    description = "ARN of the target group. Useful for passing to your Auto Scaling group module."
    value       = "${aws_lb_target_group.alb_target_group.arn}"
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir alb && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region                  = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
    profile                 = "default"
}
module "iam" {
    source                          = "../../modules/iam"
    name                            = "My-Security"
    region                          = "us-east-1"
    environment                     = "PROD"

    aws_iam_role-principals         = [
        "ec2.amazonaws.com",
    ]
    aws_iam_policy-actions           = [
        "cloudwatch:GetMetricStatistics",
        "logs:DescribeLogStreams",
        "logs:GetLogEvents",
        "elasticache:Describe*",
        "rds:Describe*",
        "rds:ListTagsForResource",
        "ec2:DescribeAccountAttributes",
        "ec2:DescribeAvailabilityZones",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeVpcs",
        "ec2:Owner",
    ]
}
module "vpc" {
    source                              = "../../modules/vpc"
    name                                = "My"
    environment                         = "PROD"
    # VPC
    instance_tenancy                    = "default"
    enable_dns_support                  = "true"
    enable_dns_hostnames                = "true"
    assign_generated_ipv6_cidr_block    = "false"
    enable_classiclink                  = "false"
    vpc_cidr                            = "172.31.0.0/16"
    private_subnet_cidrs                = ["172.31.32.0/20", "172.31.48.0/20"]
    public_subnet_cidrs                 = ["172.31.80.0/20"]
    availability_zones                  = ["us-east-1a", "us-east-1e"]
    enable_all_egress_ports             = "true"
    allowed_ports                       = ["8080", "3306", "443", "80"]

    map_public_ip_on_launch             = "true"

    #Internet-GateWay
    enable_internet_gateway             = "true"
    #NAT
    enable_nat_gateway                  = "false"
    single_nat_gateway                  = "true"
    #VPN
    enable_vpn_gateway                  = "false"
    #DHCP
    enable_dhcp_options                 = "false"
    # EIP
    enable_eip                          = "false"
}
module "ec2" {
    source                              = "../../modules/ec2"
    name                                = "TEST-Machine"
    region                              = "us-east-1"
    environment                         = "PROD"
    number_of_instances                 = 1
    ec2_instance_type                   = "t2.micro"
    enable_associate_public_ip_address  = "true"
    disk_size                           = "8"
    tenancy                             = "${module.vpc.instance_tenancy}"
    iam_instance_profile                = "${module.iam.instance_profile_id}"
    subnet_id                           = "${element(module.vpc.vpc-publicsubnet-ids, 0)}"
    #subnet_id                           = "${element(module.vpc.vpc-privatesubnet-ids, 0)}"
    #subnet_id                           = ["${element(module.vpc.vpc-privatesubnet-ids)}"]
    vpc_security_group_ids              = ["${module.vpc.security_group_id}"]

    monitoring                          = "true"
}
#module "kms" {
#    source               = "../../modules/kms"
#    name                 = "TEST-KMS"
#    environment          = "PROD"
#
#    aws_account_id       = "XXXXXXXXXXXXXXXXX"
#}
#module "s3" {
#    source                              = "../../modules/s3"
#    name                                = "My-backet"
#    environment                         = "PROD"
#
#    #
#    s3_acl          = "log-delivery-write"  #"private"
#    force_destroy   = "true"
#    # Allow public web-site (Static website hosting)
#    website         = [
#    {
#        index_document = "index.html"
#        error_document = "error.html"
#        #redirect_all_requests_to = "https://s3-website.linux-notes.org"
#    },
#    ]
#    # Use cors rules
#    cors_rule       = [
#    {
#        allowed_headers = ["*"]
#        allowed_methods = ["PUT", "POST"]
#        allowed_origins = ["https://s3-website.linux-notes.org"]
#        expose_headers  = ["ETag"]
#        max_age_seconds = 3000
#    },
#    ]
#
#    kms_master_key_id = "arn:aws:kms:${module.kms.region}:${module.kms.aws_account_id}:key/${module.kms.kms_key_id}"
#}
module "alb" {
    source                  = "../../modules/alb"
    name                    = "App-Load-Balancer"
    region                  = "us-east-1"
    environment             = "PROD"

    load_balancer_type          = "application"
    security_groups             = ["${module.vpc.security_group_id}", "${module.vpc.default_security_group_id}"]
    subnets                     = ["${module.vpc.vpc-privatesubnet-ids}"]
    vpc_id                      = "${module.vpc.vpc_id}"
    enable_deletion_protection  = false

    backend_protocol    = "HTTP"
    alb_protocols       = "HTTP"

    target_ids          = ["${module.ec2.instance_ids}"]

    #access_logs = [
    #    {
    #        enabled         = true
    #        bucket          = "${module.s3.bucket_name}"
    #        prefix          = "log"
    #    },
    #]

}

Еще полезности:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS S3 и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Работа с AWS SNS и Terraform в Unix/Linux

Работа с AWS SQS и Terraform в Unix/Linux

Работа с AWS KMS и Terraform в Unix/Linux

Работа с AWS NLB и Terraform в Unix/Linux

Работа с AWS CloudWatch и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с AWS ALB и Terraform в Unix/Linux» завершена.

Установка s-tui в Unix/Linux

$
0
0

Установка s-tui в Unix/Linux

S-tui — бесплатный пользовательский интерфейс с открытым исходным кодом для мониторинга вашего компьютера. Утилита s-tui позволяет контролировать температуру процессора, частоту и его мощность. Данная тулза, написана на Python и требует root права для ее использования.

Установка s-tui в Unix/Linux

Для этой утилиты, понадобится PIP, установить его можно по следующей статье:

Установка pip/setuptools/wheel в Unix/Linux

Так же, понадобится утилита stress.

Установка stress в Mac OS X

Стоит установить homebrew — Установка homebrew на Mac OS X и после чего, выполняем:

$ brew install stress

Установка stress в Debian/Ubuntu

Установка очень простая, выполняем:

# apt-get install stress

Установка stress в CentOS/Redhat/Fedora

Установка очень простая, выполняем:

# yum -y install stress

Установка s-tui в Unix/Linux

Чтобы установить утилиту s-tui выполняем:

# pip install s-tui

ИЛИ:

# pip3 install s-tui

Перейдем к использованию.

Использование s-tui в Unix/Linux

Использование очень простое, стоит выполнить:

$ sudo s-tui

Вот как выглядит утилита в работе:

Установка s-tui в Unix/Linux

Для помощи, можно использовать команду:

$ s-tui --help

Вот и все, статья «Установка s-tui в Unix/Linux» завершена.

Работа с AWS MQ broker и Terraform в Unix/Linux

$
0
0

Работа с AWS MQ broker и Terraform в Unix/Linux

Amazon MQ – управляемый сервис брокера сообщений для Apache ActiveMQ. Он позволяет без труда настраивать в облаке брокеры сообщений и работать с ними. Брокеры сообщений обеспечивают различным программным системам – зачастую написанным на разных языках программирования для различных платформ – возможность связываться между собой и обмениваться информацией. Система обмена сообщениями – это коммуникационная магистраль, позволяющая связать и интегрировать компоненты распределенных приложений, например систем обработки заказов, складского учета и выполнения заказов в интернет-коммерции. Сервис Amazon MQ работает с популярным брокером сообщений ActiveMQ с открытым исходным кодом, осуществляя управление системой и ее обслуживание. Ресурсы базовой инфраструктуры автоматически выделяются для обеспечения высокой доступности и сохранности сообщений, поддерживая таким образом надежную работу приложений. Amazon MQ позволяет получить прямой доступ к консоли ActiveMQ, а также стандартным отраслевым API и протоколам службы сообщений, в том числе JMS, NMS, AMQP, STOMP, MQTT и WebSocket. Перейти на Amazon MQ с любого другого брокера сообщений, использующего перечисленные стандарты, очень просто: переписывать программный код приложений в части обмена сообщениями не потребуется.

Начать работу с Amazon MQ легко. Запустить брокер сообщений можно за считаные минуты в Консоли управления AWS или с помощью интерфейса командной строки (CLI). Amazon MQ не требует предварительных вложений в аппаратное или программное обеспечение и минимальных платежей. Оплачивается только фактическое использование инстанса брокера и хранилища.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS MQ broker и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/mq

Переходим в нее:

$ cd modules/mq

Открываем файл:

$ vim mq.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS MQ broker
#---------------------------------------------------
resource "aws_mq_broker" "mq_broker" {

    broker_name             = "${lower(var.name)}-mq-broker-${lower(var.environment)}"
    engine_type             = "${var.engine_type}"
    engine_version          = "${var.engine_version}"
    host_instance_type      = "${var.host_instance_type}"
    security_groups         = ["${var.security_group_ids}"]
    subnet_ids              = ["${var.subnet_ids}"]

    apply_immediately           = "${var.apply_immediately}"
    auto_minor_version_upgrade  = "${var.auto_minor_version_upgrade}"
    deployment_mode             = "${var.deployment_mode}"
    publicly_accessible         = "${var.publicly_accessible}"

    maintenance_window_start_time {
        day_of_week = "${var.day_of_week}"
        time_of_day = "${var.time_of_day}"
        time_zone   = "${var.time_zone}"
    }

    configuration {
        id          = "${aws_mq_configuration.mq_configuration.id}"
        revision    = "${aws_mq_configuration.mq_configuration.latest_revision}"
    }

    user {
        username        = "${var.mq_broker_username}"
        password        = "${var.mq_broker_password}"
        groups          = ["${var.mq_broker_groups}"]
        console_access  = "${var.mq_broker_console_access}"
    }

    depends_on = ["aws_mq_configuration.mq_configuration"]
}
#---------------------------------------------------
# Create AWS MQ broker configuration
#---------------------------------------------------
resource "aws_mq_configuration" "mq_configuration" {
    name           = "${lower(var.name)}-mq-broker-configuration-${lower(var.environment)}"
    description    = "The Configuration for ${lower(var.name)}-mq-broker-${lower(var.environment)}"
    engine_type    = "${var.engine_type}"
    engine_version = "${var.engine_version}"
    data           = "${data.template_file.mq_configuration_data.rendered}"

    depends_on  = ["data.template_file.mq_configuration_data"]
}
#---------------------------------------------------
# Create data for AWS MQ broker configuration
#---------------------------------------------------
data "template_file" "mq_configuration_data" {
    template = "${file("${path.module}/data/data.xml.tpl")}"
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-MQ"
}

variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}

variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}

variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}

variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}

variable "engine_type" {
    description = "The type of broker engine. Currently, Amazon MQ supports only ActiveMQ."
    default     = "ActiveMQ"
}

variable "engine_version" {
    description = "The version of the broker engine. Currently, Amazon MQ supports only 5.15.0"
    default     = "5.15.0"
}

variable "host_instance_type" {
    description = "The broker's instance type. e.g. mq.t2.micro or mq.m4.large"
    default     = "mq.t2.micro"
}

variable "security_group_ids" {
    description = "The list of security group IDs assigned to the broker."
    default     = []
}

variable "subnet_ids" {
    description = "The list of subnet IDs in which to launch the broker. A SINGLE_INSTANCE deployment requires one subnet. An ACTIVE_STANDBY_MULTI_AZ deployment requires two subnets."
    default     = []
}

variable "apply_immediately" {
    description = "Specifies whether any broker modifications are applied immediately, or during the next maintenance window. Default is false."
    default     = "false"
}

variable "auto_minor_version_upgrade" {
    description = "Enables automatic upgrades to new minor versions for brokers, as Apache releases the versions."
    default     = "false"
}

variable "deployment_mode" {
    description = "The deployment mode of the broker. Supported: SINGLE_INSTANCE and ACTIVE_STANDBY_MULTI_AZ. Defaults to SINGLE_INSTANCE."
    default     = "SINGLE_INSTANCE"
}

variable "publicly_accessible" {
    description = "Whether to enable connections from applications outside of the VPC that hosts the broker's subnets."
    default     = "false"
}

variable "mq_broker_username" {
    description = "The username of the user."
    default     = "mq_broker"
}

variable "mq_broker_password" {
    description = "The password of the user. It must be 12 to 250 characters long, at least 4 unique characters, and must not contain commas."
    default     = "mq_broker666"
}

variable "mq_broker_groups" {
    description = "The list of groups (20 maximum) to which the ActiveMQ user belongs."
    type        = "list"
    default     = ["mq_broker"]
}

variable "mq_broker_console_access" {
    description = "Whether to enable access to the the ActiveMQ Web Console for the user."
    default     = "true"
}

variable "day_of_week" {
    description = "The day of the week. e.g. MONDAY, TUESDAY, or WEDNESDAY"
    default     = "MONDAY"
}

variable "time_of_day" {
    description = "The time, in 24-hour format. e.g. 02:00"
    default     = "02:00"
}

variable "time_zone" {
    description = "The time zone, UTC by default, in either the Country/City format, or the UTC offset format. e.g. CET"
    default     = "UTC"
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "mq_broker_ids" {
    description = ""
    value       = "${aws_mq_broker.mq_broker.*.id}"
}

output "mq_broker_arns" {
    description = ""
    value       = "${aws_mq_broker.mq_broker.*.arn}"
}

output "mq_broker_instances" {
    description = ""
    value       = "${aws_mq_broker.mq_broker.*.instances}"
}

output "mq_configuration_ids" {
    description = ""
    value       = "${aws_mq_configuration.mq_configuration.*.id}"
}

output "mq_configuration_arns" {
    description = ""
    value       = "${aws_mq_configuration.mq_configuration.*.arn}"
}

output "mq_configuration_latest_revision" {
    description = ""
    value       = "${aws_mq_configuration.mq_configuration.*.latest_revision}"
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir mq && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region                  = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
    profile                 = "default"
}
module "vpc" {
    source                              = "../../modules/vpc"
    name                                = "TEST-VPC"
    environment                         = "PROD"
    # VPC
    instance_tenancy                    = "default"
    enable_dns_support                  = "true"
    enable_dns_hostnames                = "true"
    assign_generated_ipv6_cidr_block    = "false"
    enable_classiclink                  = "false"

    vpc_cidr                            = "172.31.0.0/16"
    private_subnet_cidrs                = ["172.31.64.0/20"]
    public_subnet_cidrs                 = ["172.31.80.0/20", "172.31.0.0/20"]
    availability_zones                  = ["us-east-1a", "us-east-1b"]
    allowed_ports                       = ["8080", "3306", "80", "443", "5672"]

    #Internet-GateWay
    enable_internet_gateway             = "true"
    #NAT
    enable_nat_gateway                  = "false"
    single_nat_gateway                  = "true"
    #VPN
    enable_vpn_gateway                  = "false"
    #DHCP
    enable_dhcp_options                 = "false"
    # EIP
    enable_eip                          = "false"
}
module "mq" {
    source                          = "../../modules/mq"
    name                            = "TEST-MQ"
    region                          = "us-east-1"
    environment                     = "PROD"

    security_group_ids     = ["${module.vpc.security_group_id}", "${module.vpc.default_security_group_id}"]
    subnet_ids             = ["${module.vpc.vpc-privatesubnet-ids}"]
}

Еще полезности:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS S3 и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Работа с AWS SNS и Terraform в Unix/Linux

Работа с AWS SQS и Terraform в Unix/Linux

Работа с AWS KMS и Terraform в Unix/Linux

Работа с AWS NLB и Terraform в Unix/Linux

Работа с AWS CloudWatch и Terraform в Unix/Linux

Работа с AWS ALB и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с AWS MQ broker и Terraform в Unix/Linux» завершена.

Работа с AWS EFS и Terraform в Unix/Linux

$
0
0

Работа с AWS EFS и Terraform в Unix/Linux

Amazon EFS – это полностью управляемый сервис, который позволяет легко настраивать и масштабировать файловое хранилище в облаке Amazon. С помощью нескольких щелчков мышью в Консоли управления AWS можно создать файловые системы, которые будут доступны для инстансов Amazon EC2 через интерфейс файловой системы (с использованием API ввода-вывода файлов стандартной операционной системы), который поддерживает полную семантику доступа к файловой системе (например, строгую непротиворечивость и блокировку файлов).

Файловые системы Amazon EFS обеспечивают автоматическое масштабирование от нескольких гигабайтов до петабайтов данных без необходимости предоставления хранилища. Десятки, сотни или даже тысячи инстансов Amazon EC2 могут одновременно получать доступ к файловой системе Amazon EFS, при этом Amazon EFS обеспечивает стабильную производительность для каждого инстанса Amazon EC2. Система Amazon EFS отличается высокой доступностью и надежностью. С Amazon EFS вы платите только за реально используемый объем хранилища файлов, минимальные взносы и стартовые платежи отсутствуют.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS EFS и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/efs

Переходим в нее:

$ cd modules/efs

Открываем файл:

$ vim efs.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS EFS file system
#---------------------------------------------------
resource "aws_efs_file_system" "efs_file_system" {
    creation_token      = "${lower(var.name)}-efs-${lower(var.environment)}"
    performance_mode    = "${var.performance_mode}"
    creation_token      = "${var.creation_token}"
    encrypted           = "${var.encrypted}"
    kms_key_id          = "${var.kms_key_id}"

    tags {
        Name            = "${lower(var.name)}-efs-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }

}
#---------------------------------------------------
# Create AWS EFS mount target
#---------------------------------------------------
resource "aws_efs_mount_target" "efs_mount_target" {
    count           = "${length(var.subnet_ids) > 0 ? length(var.subnet_ids) : 0}"

    file_system_id  = "${aws_efs_file_system.efs_file_system.id}"
    subnet_id       = "${data.template_file.subnet_id.rendered}"
}

data "template_file" "subnet_id" {
    count    = "${length(var.subnet_ids) > 0 ? length(var.subnet_ids) : 0}"
    template = "${element(var.subnet_ids, count.index)}"
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-codedeploy"
}

variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}

variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}

variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}

variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}

variable "performance_mode" {
    description = "The file system performance mode. Can be either 'generalPurpose' or 'maxIO' (Default: 'generalPurpose')."
    default     = "generalPurpose"
}

variable "encrypted" {
    description = "If true, the disk will be encrypted."
    default     = "true"
}

variable "kms_key_id" {
    description = "The ARN for the KMS encryption key. When specifying kms_key_id, encrypted needs to be set to true."
    default     = ""
}

variable "creation_token" {
    description = "DEPRECATED (Optional) A reference name used when creating the Creation Token which Amazon EFS uses to ensure idempotent file system creation. By default generated by Terraform."
    default     = ""
}

variable "subnet_ids" {
    description = "The ID of the subnets to add the mount target in."
    type        = "list"
    default     = []
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "efs_file_system_ids" {
    description = ""
    value       = "${aws_efs_file_system.efs_file_system.*.id}"
}

output "efs_file_system_kms_key_ids" {
    description = ""
    value       = "${aws_efs_file_system.efs_file_system.*.kms_key_id}"
}

output "efs_file_system_dns_names" {
    description = ""
    value       = "${aws_efs_file_system.efs_file_system.*.dns_name}"
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir efs && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region                  = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
    profile                 = "default"
}
module "vpc" {
    source                              = "../../modules/vpc"
    name                                = "TEST-VPC"
    environment                         = "PROD"
    # VPC
    instance_tenancy                    = "dedicated"
    enable_dns_support                  = "true"
    enable_dns_hostnames                = "true"
    assign_generated_ipv6_cidr_block    = "false"
    enable_classiclink                  = "false"

    vpc_cidr                            = "172.31.0.0/16"
    private_subnet_cidrs                = ["172.31.64.0/20"]
    public_subnet_cidrs                 = ["172.31.80.0/20", "172.31.0.0/20"]
    availability_zones                  = ["us-east-1a", "us-east-1b"]
    allowed_ports                       = ["8080", "3306", "80", "443"]

    #Internet-GateWay
    enable_internet_gateway             = "true"
    #NAT
    enable_nat_gateway                  = "false"
    single_nat_gateway                  = "true"
    #VPN
    enable_vpn_gateway                  = "false"
    #DHCP
    enable_dhcp_options                 = "false"
    # EIP
    enable_eip                          = "false"
}
module "efs" {
    source          = "../../modules/efs"
    name            = "TEST-EFS"
    region          = "us-east-1"
    environment     = "PROD"

    subnet_ids      = ["${module.vpc.vpc-privatesubnet-ids}"]
}

Еще полезности:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS S3 и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Работа с AWS SNS и Terraform в Unix/Linux

Работа с AWS SQS и Terraform в Unix/Linux

Работа с AWS KMS и Terraform в Unix/Linux

Работа с AWS NLB и Terraform в Unix/Linux

Работа с AWS CloudWatch и Terraform в Unix/Linux

Работа с AWS ALB и Terraform в Unix/Linux

Работа с AWS MQ broker и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с AWS EFS и Terraform в Unix/Linux» завершена.

Установка Go/Golang в Unix/Linux

$
0
0

Установка Go/Golan в Unix/Linux

Go (часто также Golang) — компилируемый многопоточный язык программирования, разработанный внутри компании Google. Первоначальная разработка Go началась в сентябре 2007 года, а его непосредственным проектированием занимались Роберт Гризмер, Роб Пайк и Кен Томпсон, занимавшиеся до этого проектом разработки операционной системы Inferno. Официально язык был представлен в ноябре 2009 года. На данный момент его поддержка осуществляется для операционных систем FreeBSD, OpenBSD, Linux, Mac OS X, начиная с версии 1.3 в язык Go включена экспериментальная поддержка DragonFly BSD, Plan 9 и Solaris, начиная с версии 1.4 — поддержка платформы Android.

Установка Go/Golang в Unix/Linux

Приведу примеры установок на несколько Unix/Linux ОС.

Установка Go/Golang на Linux

Перейдем в папку и скачаем архив:

$ cd /usr/local/src && wget --no-check-certificate https://dl.google.com/go/go1.10.linux-amd64.tar.gz

PS: На момент написания статьи, я использовал самую новую версию ПО.

Выполняем распаковку:

# tar xfvz go*.linux-amd64.tar.gz -C /usr/local/

Установка Go/Golang на Mac OS X

Перейдем в папку и скачаем архив:

$ cd /usr/local/src && wget --no-check-certificate  https://dl.google.com/go/go1.10.darwin-amd64.pkg

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

$ sudo installer -pkg go1.10.darwin-amd64.pkg -target /

Вот статья как установить .DMG в Mac OS X:

Установка dmg пакетов через CLI (командную строку) в MacOS X

Установка Go/Golang на др Unix/Linux ОС

  1. Можно использовать doker
  2. Можно попробовать скомпилировать go с исходного кода.

Настройка Go/Golang в Unix/Linux

Затем в домашнем каталоге пользователя создайте рабочую папку для проектов Go с тремя дочерними каталогами, bin, src и pkg. Каталог bin будет содержать исполняемые программы, скомпилированные из файлов, читаемых человеком, в каталоге src. В каталоге pkg хранятся объекты пакета, которые являются многоразовыми кодами, совместно используемыми между программами:

$ mkdir -p ~/Projects/GO/{bin,pkg,src}

Почти все готово к использованию.

Чтобы запускать Go (как и любую другую команду), нужно добавить ее место установки в переменную $PATH. Go был установлен в системном каталоге, поэтому мы будем устанавливать глобальную переменную среды:

# vim  /etc/profile.d/path.sh

и прописываем в него:

export PATH=$PATH:/usr/local/go/bin

PS: Можно тоже самое сделать в ~/.bash_profile файле. Кому как удобно!

Идем делаьше, стоит добавить пути, для этого открываем:

# vim ~/.bash_profile

И вставляем:

[...]
export PATH=$PATH:/usr/local/go/bin:$HOME/bin:/usr/local/bin:/usr/local/sbin:/usr/local/git/bin:/sbin:/bin:/opt/local/bin:/opt/local/sbin
export GOBIN="$HOME/Projects/GO/bin"
export GOPATH="$HOME/Projects/GO/src"
export GOROOT="/usr/local/go"
[...]

Применяем:

# . ~/.bash_profile

Вот и вся настройка.

Использование Go/Golang в Unix/Linux

Для проверки версии ПО, выполните:

$ go version

Так же, проверим — все ли переменные среды (ENV) определены, используя следующую команду:

$ go env

На моем mac OS X, вот какой вывод:

GOARCH="amd64"
GOBIN="/Users/captain/Projects/GO/bin"
GOCACHE="/Users/captain/Library/Caches/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/captain/Projects/GO/src"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/9s/_8tkgh_x58b4r9fgbll6z3sm0000gn/T/go-build577665108=/tmp/go-build -gno-record-gcc-switches -fno-common"

Пришим простую программу, — конечно же — хеллоу ворлд. Открываем:

$ vim ~/Projects/GO/src/hello.go

В файл прописываем:

package main

import "fmt"

func main() {
    fmt.Printf("Hello, World!\n")
}

Запускаем писанину вот так:

$ go install $GOPATH/hello.go

Скомпилированная тулза появится в «bin» папке вашего проекта. Запустим его:

$ $GOBIN/hello

Получим:

Hello, World!

Вот и все, статья «Установка GO в Unix/Linux» завершена.

Работа с AWS elasticache и Terraform в Unix/Linux

$
0
0

Работа с AWS elasticache и Terraform в Unix/Linux

Amazon ElastiCache – это веб-сервис, упрощающий развертывание и масштабирование в облаке хранилища или кэша в памяти, а также управление ими. Сервис повышает производительность интернет-приложений, позволяя получать информацию не только из баз данных, размещенных на дисках, но и из управляемых хранилищ данных в памяти, которые работают быстрее и безопаснее. Amazon ElastiCache поддерживает два сервиса с открытым исходным кодом для размещения данных в памяти.

  • Redis – быстрое хранилище данных и кэш в памяти с открытым исходным кодом. Amazon ElastiCache для Redis – это совместимый с Redis сервис хранения и кэширования данных в памяти, который обеспечивает простоту использования и функциональность Redis, а также доступность, надежность, масштабируемость и производительность, подходящие для самых требовательных приложений. Доступны как кластеры, состоящие из одного узла, так и кластеры, включающие до 15 сегментов, что обеспечивает масштабируемость до 3,55 ТиБ данных в памяти. Сервис поддерживает изменение размера работающего кластера, что позволяет без простоя масштабировать кластеры Redis в сторону увеличения или в сторону уменьшения и адаптироваться к изменяющемуся спросу. Сервис соответствует требованиям HIPAA и предлагает шифрование данных при передаче и хранении, а также Redis AUTH для безопасной передачи данных между узлами и надежного хранения конфиденциальных данных, таких как персональная информация (PII). ElastiCache для Redis – это полностью управляемый, масштабируемый и безопасный сервис. Он идеально подходит для высокопроизводительных примеров использования, таких как мобильные и интернет-приложения, приложения, используемые в здравоохранении и финансовой сфере, игры, рекламные технологии и «Интернет вещей».
  • Memcached – широко распространенная система кэширования объектов в памяти. Используемые в ElastiCache протоколы полностью совместимы с Memcached, поэтому все популярные инструменты, уже используемые в существующих средах Memcached, будут эффективно работать с этим сервисом.

Amazon ElastiCache автоматически определяет и заменяет вышедшие из строя узлы, снижая издержки, связанные с самоуправляемыми инфраструктурами, и формирует отказоустойчивую систему, которая сводит к минимуму риск перегрузок баз данных и его негативное влияние на время загрузки веб-сайтов и приложений. Благодаря интеграции с Amazon CloudWatch сервис Amazon ElastiCache предлагает расширенные возможности мониторинга ключевых показателей производительности, связанных с узлами Redis или Memcached.

С помощью Amazon ElastiCache вы сможете добавить уровень данных в памяти в свою инфраструктуру за считанные минуты, используя Консоль управления AWS.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с AWS elasticache и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/elasticache

Переходим в нее:

$ cd modules/elasticache

Открываем файл:

$ vim elasticache.tf

В данный файл, вставляем:

#---------------------------------------------------
# Create AWS elasticache security group (SG)
#---------------------------------------------------
resource "aws_elasticache_security_group" "elasticache_sg" {
    # NOTE: ElastiCache Subnet Groups are only for use when working with an ElastiCache cluster inside of a VPC. If you are on EC2 Classic, see the ElastiCache Security Group resource.
    # NOTE: ElastiCache Security Groups are for use only when working with an ElastiCache cluster outside of a VPC. If you are using a VPC, see the ElastiCache Subnet Group resource.
    count                = "${length(var.security_group_names) !=0 && length(var.subnet_ids) ==0 ? 1 : 0}"

    name                 = "${lower(var.name)}-${var.engine}-sg-${lower(var.environment)}"
    description          = "Elasticache security group (SG) which managed by ${var.orchestration}"
    security_group_names = ["${var.security_group_names}"]
}
#---------------------------------------------------
# Create AWS elasticache subnet group
#---------------------------------------------------
resource "aws_elasticache_subnet_group" "elasticache_subnet_group" {
    # NOTE: ElastiCache Subnet Groups are only for use when working with an ElastiCache cluster inside of a VPC. If you are on EC2 Classic, see the ElastiCache Security Group resource.
    # NOTE: ElastiCache Security Groups are for use only when working with an ElastiCache cluster outside of a VPC. If you are using a VPC, see the ElastiCache Subnet Group resource.
    count       = "${length(var.subnet_ids) !=0 && length(var.security_group_names) ==0 ? 1 : 0}"

    name        = "${lower(var.name)}-${var.engine}-subnet-group-${lower(var.environment)}"
    description = "Elasticache subnet group which managed by ${var.orchestration}"
    subnet_ids  = ["${var.subnet_ids}"]
}
#---------------------------------------------------
# Create AWS elasticache parameter group
#---------------------------------------------------
resource "aws_elasticache_parameter_group" "elasticache_parameter_group" {
    count       = "${length(var.parameters_for_parameter_group) !=0 && var.create_custom_elasticache_parameter_group ? 1 : 0}"

    name        = "${lower(var.name)}-${var.engine}-parameter-group-${lower(var.environment)}"
    description = "Elasticache parameter group which managed by ${var.orchestration}"
    family      = "${var.elasticache_parameter_group_family[var.engine]}"

    parameter = ["${var.parameters_for_parameter_group}"]
}
#---------------------------------------------------
# Create AWS elasticache cluster
#---------------------------------------------------
resource "aws_elasticache_cluster" "elasticache_cluster" {
    count                   = "${var.num_cache_nodes ==1 && var.number_cluster_replicas ==0 && var.create_single_cluster ? 1 : 0}"

    cluster_id              = "${lower(var.name)}-${lower(var.engine)}-${lower(var.environment)}"
    engine                  = "${var.engine}"
    node_type               = "${var.node_type}"
    port                    = "${var.default_ports[var.engine]}"
    num_cache_nodes         = "${var.num_cache_nodes}"

    subnet_group_name       = "${var.subnet_group_name}"
    security_group_names    = ["${var.security_group_names_for_cluster}"]
    security_group_ids      = ["${var.security_group_ids}"]
    parameter_group_name    = "${var.parameter_group_name[var.engine] !="" ? var.parameter_group_name[var.engine] : aws_elasticache_parameter_group.elasticache_parameter_group.name}"

    maintenance_window          = "${var.maintenance_window}"
    snapshot_window             = "${var.snapshot_window}"
    #snapshot_retention_limit    = "${var.snapshot_retention_limit }"

    availability_zone       = "${var.availability_zone}"
    notification_topic_arn  = "${var.notification_topic_arn}"

    tags {
        Name            = "${lower(var.name)}-${var.engine}-cluster-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
}

#---------------------------------------------------
# Create AWS elasticache replication group
#---------------------------------------------------
resource "aws_elasticache_replication_group" "elasticache_replication_group" {
    # Redis Master with One Replica with 1 shard
    count                         = "${var.num_cache_nodes >1 && var.number_cluster_replicas ==1 && var.create_single_cluster !="true" ? 1 : 0}"

    replication_group_id          = "${lower(var.name)}-${lower(var.engine)}-${lower(var.environment)}"
    replication_group_description = "The ${var.engine} master with 1 replica shard which managed by ${var.orchestration}"
    node_type                     = "${var.node_type}"
    number_cache_clusters         = "${var.num_cache_nodes}"
    port                          = "${var.default_ports[var.engine]}"
    engine                        = "${var.engine}"
    engine_version                = "${var.engine_version}"

    availability_zones              = ["us-east-1a", "us-east-1c"]
    automatic_failover_enabled      = "${var.automatic_failover_enabled}"
    subnet_group_name               = "${var.subnet_group_name}"
    security_group_names            = ["${var.security_group_names_for_cluster}"]
    security_group_ids              = ["${var.security_group_ids}"]
    parameter_group_name            = "${var.parameter_group_name[var.engine] !="" ? var.parameter_group_name[var.engine] : aws_elasticache_parameter_group.elasticache_parameter_group.name}"
    at_rest_encryption_enabled      = "${var.at_rest_encryption_enabled}"
    transit_encryption_enabled      = "${var.transit_encryption_enabled}"
    #auth_token                      = "${var.auth_token}"

    auto_minor_version_upgrade  = "${var.auto_minor_version_upgrade}"
    snapshot_name               = "${var.snapshot_name}"
    maintenance_window          = "${var.maintenance_window}"
    snapshot_window             = "${var.snapshot_window}"
    snapshot_retention_limit    = "${var.snapshot_retention_limit}"
    apply_immediately           = "${var.apply_immediately}"

    notification_topic_arn  = "${var.notification_topic_arn}"

    tags {
        Name            = "${lower(var.name)}-${var.engine}-cluster-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
}

resource "aws_elasticache_replication_group" "elasticache_replication_group_2" {
    # Redis Master with One Replica for each nodes
    count                         = "${var.num_cache_nodes >1 && var.number_cluster_replicas ==2 && var.create_single_cluster !="true" ? 1 : 0}"

    replication_group_id          = "${lower(var.name)}-${lower(var.engine)}-${lower(var.environment)}"
    replication_group_description = "The ${var.engine} master with 2 replica shards which managed by ${var.orchestration}"
    node_type                     = "${var.node_type}"
    port                          = "${var.default_ports[var.engine]}"
    engine                        = "${var.engine}"
    engine_version                = "${var.engine_version}"

    automatic_failover_enabled      = "${var.automatic_failover_enabled}"
    subnet_group_name               = "${var.subnet_group_name}"
    security_group_names            = ["${var.security_group_names_for_cluster}"]
    security_group_ids              = ["${var.security_group_ids}"]
    parameter_group_name            = "${var.parameter_group_name[var.engine] !="" ? var.parameter_group_name[var.engine] : aws_elasticache_parameter_group.elasticache_parameter_group.name}"
    at_rest_encryption_enabled      = "${var.at_rest_encryption_enabled}"
    transit_encryption_enabled      = "${var.transit_encryption_enabled}"
    #auth_token                      = "${var.auth_token}"

    auto_minor_version_upgrade  = "${var.auto_minor_version_upgrade}"
    snapshot_name               = "${var.snapshot_name}"
    maintenance_window          = "${var.maintenance_window}"
    snapshot_window             = "${var.snapshot_window}"
    snapshot_retention_limit    = "${var.snapshot_retention_limit}"
    apply_immediately           = "${var.apply_immediately}"

    notification_topic_arn  = "${var.notification_topic_arn}"

    cluster_mode {
        replicas_per_node_group     = "${var.cluster_mode_replicas_per_node_group}"
        num_node_groups             = "${var.num_cache_nodes}"
    }

    lifecycle {
        create_before_destroy   = true,
    }

    tags {
        Name            = "${lower(var.name)}-${var.engine}-cluster-${lower(var.environment)}"
        Environment     = "${var.environment}"
        Orchestration   = "${var.orchestration}"
        Createdby       = "${var.createdby}"
    }
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-elasticache"
}

variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}

variable "environment" {
    description = "Environment for service"
    default     = "STAGE"
}

variable "orchestration" {
    description = "Type of orchestration"
    default     = "Terraform"
}

variable "createdby" {
    description = "Created by"
    default     = "Vitaliy Natarov"
}

variable "security_group_names" {
    description = "List of EC2 security group names to be authorized for ingress to the cache security group"
    type        = "list"
    default     = []
}

variable "subnet_ids" {
    description = "List of VPC Subnet IDs for the cache subnet group"
    type        = "list"
    default     = []
}

variable "parameters_for_parameter_group" {
    description = "List of parameters for custom elasticache parameter group"
    type        = "list"
    default     = []
}

variable "create_custom_elasticache_parameter_group" {
    description = "If true, will create elasticache parameter group"
    default     = "true"
}

variable "engine" {
    description = "Name of the cache engine to be used for this cache cluster. Valid values for this parameter are memcached or redis"
    default     = "redis"
}

variable "engine_version" {
    description = "The version number of the cache engine to be used for the cache clusters in this replication group."
    default     = ""
}

variable "default_ports" {
    description = "Default database ports"
    type        = "map"
    default     = {
        redis       = "6379"
        memcached   = "11211"
    }
}

variable "elasticache_parameter_group_family" {
    description = "Set DB group family"
    type        = "map"
    default     = {
        redis       = "redis3.2"
        memcached   = "memcached1.4"
    }
}

variable "create_single_cluster" {
    description = "Enable to create a cluster without any replicas. Default - true"
    default     = "true"
}

variable "node_type" {
    description = "The cluster node type. Ex: cache.t2.micro"
    default     = "cache.t2.micro"
}

variable "num_cache_nodes" {
    description = "The number of cache nodes that the cache cluster has.  Cannot create a Redis cluster with a NumCacheNodes parameter greater than 1."
    default     = "1"
}

variable "parameter_group_name" {
    description = "Name of the parameter group associated with this cache cluster. Ex: default.redis3.2, default.memcached1.4 etc"
    type        = "map"
    default     = {
        redis       = ""
        memcached   = ""
    }
}

variable "subnet_group_name" {
    description = "Name of the subnet group associated to the cache cluster."
    default     = ""
}

variable "security_group_names_for_cluster" {
    description = "List of security group names associated with this cache cluster."
    type        = "list"
    default     = []
}

variable "security_group_ids" {
    description = "List VPC security groups associated with the cache cluster."
    type        = "list"
    default     = []
}

variable "maintenance_window" {
    description = "Specifies the weekly time range for when maintenance on the cache cluster is performed. The format is ddd:hh24:mi-ddd:hh24:mi (24H Clock UTC). The minimum maintenance window is a 60 minute period. Example: sun:05:00-sun:09:00"
    default     = "sun:05:00-sun:09:00"
}

variable "snapshot_window" {
    description = "The daily time range (in UTC) during which ElastiCache will begin taking a daily snapshot of the cache cluster. Format: hh24:mi-hh24:mi. The minimum snapshot window is a 60 minute period. Example: 05:00-09:00"
    default     = "01:00-05:00"
}

variable "availability_zone" {
    description = "The Availability Zone for the cache cluster."
    default     = ""
}

variable "notification_topic_arn" {
    description = "An Amazon Resource Name (ARN) of an SNS topic that ElastiCache notifications get sent to."
    default     = ""
}

variable "snapshot_retention_limit" {
    description = "The number of days for which ElastiCache will retain automatic cache cluster snapshots before deleting them. For example, if you set SnapshotRetentionLimit to 5, then a snapshot that was taken today will be retained for 5 days before being deleted. If the value of SnapshotRetentionLimit is set to zero (0), backups are turned off. Please note that setting a snapshot_retention_limit is not supported on cache.t1.micro or cache.t2.* cache nodes"
    default     = "7"
}

variable "replication_group_id" {
    description = "The replication group to which this cache cluster belongs."
    default     = "replication-cluster-group"
}

variable "number_cluster_replicas" {
    description = "Number of cluster replicas which will create"
    default     = "0"
}

variable "automatic_failover_enabled" {
    description = "Specifies whether a read-only replica will be automatically promoted to read/write primary if the existing primary fails. Defaults to false."
    default     = "true"
}

variable "auto_minor_version_upgrade" {
    description = "Specifies whether a minor engine upgrades will be applied automatically to the underlying Cache Cluster instances during the maintenance window. Defaults to true."
    default     = "true"
}

variable "at_rest_encryption_enabled" {
    description = "Whether to enable encryption at rest."
    default     = "false"
}

variable "transit_encryption_enabled" {
    description = "Whether to enable encryption in transit."
    default     = "false"
}

variable "auth_token" {
    description = "The password used to access a password protected server. Can be specified only if transit_encryption_enabled = true."
    default     = "AUTHtoken666AUTHtoken666AUTHtoken666AUTHtoken666"
}

variable "snapshot_name" {
    description = "The name of a snapshot from which to restore data into the new node group. Changing the snapshot_name forces a new resource."
    default     = ""
}

variable "apply_immediately" {
    description = "Specifies whether any modifications are applied immediately, or during the next maintenance window. Default is false."
    default     = "false"
}

variable "cluster_mode_replicas_per_node_group" {
    description = "Specify the number of replica nodes in each node group. Valid values are 0 to 5. Changing this number will force a new resource."
    default     = "1"
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "elasticache_sg_ids" {
    description = ""
    value       = "${aws_elasticache_security_group.elasticache_sg.*.id}"
}

output "elasticache_subnet_group" {
    description = ""
    value       = "${aws_elasticache_subnet_group.elasticache_subnet_group.*.id}"
}

output "elasticache_parameter_group_names" {
    description = ""
    value       = "${aws_elasticache_parameter_group.elasticache_parameter_group.*.name}"
}

output "elasticache_cluster_ids" {
    description = ""
    value       = "${aws_elasticache_cluster.elasticache_cluster.*.id}"
}

output "elasticache_replication_group_ids" {
    description = ""
    value       = "${aws_elasticache_replication_group.elasticache_replication_group.*.id}"
}

output "elasticache_replication_group_2_ids" {
    description = ""
    value       = "${aws_elasticache_replication_group.elasticache_replication_group_2.*.id}"
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir elasticache && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region                  = "us-east-1"
    shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
    profile                 = "default"
}
module "vpc" {
    source                              = "../../modules/vpc"
    name                                = "TEST-VPC"
    environment                         = "PROD"
    # VPC
    instance_tenancy                    = "default"
    enable_dns_support                  = "true"
    enable_dns_hostnames                = "true"
    assign_generated_ipv6_cidr_block    = "false"
    enable_classiclink                  = "false"

    vpc_cidr                            = "172.31.0.0/16"
    private_subnet_cidrs                = ["172.31.64.0/20"]
    public_subnet_cidrs                 = ["172.31.80.0/20"]
    availability_zones                  = ["us-east-1a", "us-east-1b"]
    allowed_ports                       = ["6379", "11211"]

    allow_cidrs_for_allowed_ports       = [{
        "6379"      = ["0.0.0.0/0"]
        "11211"     = ["0.0.0.0/0"]
    }]

    #Internet-GateWay
    enable_internet_gateway             = "true"
    #NAT
    enable_nat_gateway                  = "false"
    single_nat_gateway                  = "true"
    #VPN
    enable_vpn_gateway                  = "false"
    #DHCP
    enable_dhcp_options                 = "false"
    # EIP
    enable_eip                          = "false"
}
module "elasticache" {
    source                          = "../../modules/elasticache"
    name                            = "TEST"
    region                          = "us-east-1"
    environment                     = "PROD"

    # NOTE: ElastiCache Subnet Groups are only for use when working with an ElastiCache cluster inside of a VPC. If you are on EC2 Classic, see the ElastiCache Security Group resource.
    # NOTE: ElastiCache Security Groups are for use only when working with an ElastiCache cluster outside of a VPC. If you are using a VPC, see the ElastiCache Subnet Group resource.
    # I HAVE GOT ISSUE WHEN USED "ElastiCache Security Groups". SO I PREFERED ElastiCache Subnet Groups
    #aws_elasticache_security_group.elasticache_sg: Error creating CacheSecurityGroup: InvalidParameterValue: Use of cache security groups is not permitted in this API version for your account.
    security_group_names    = []
    subnet_ids              = ["${module.vpc.vpc-privatesubnet-ids}", "${module.vpc.vpc-publicsubnet-ids}"]

    create_custom_elasticache_parameter_group   = true
    parameters_for_parameter_group              = [
    {
        name  = "activerehashing"
        value = "yes"
    },
    {
        name  = "min-slaves-to-write"
        value = "2"
    },
    ]
    engine                                      = "redis" #"memcached"

    # Not single cluster
    #create_single_cluster   = false
    #num_cache_nodes         = 2
    #number_cluster_replicas = 1
    #node_type               = "cache.m3.medium"

    # cluster with 2 nodes and 2 shards
    create_single_cluster   = false
    number_cluster_replicas = 2
    num_cache_nodes         = 2
    node_type               = "cache.m3.medium"
    parameter_group_name    = [{
        redis   = "default.redis3.2.cluster.on"
    }]

}

Еще полезности:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS S3 и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Работа с AWS SNS и Terraform в Unix/Linux

Работа с AWS SQS и Terraform в Unix/Linux

Работа с AWS KMS и Terraform в Unix/Linux

Работа с AWS NLB и Terraform в Unix/Linux

Работа с AWS CloudWatch и Terraform в Unix/Linux

Работа с AWS ALB и Terraform в Unix/Linux

Работа с AWS MQ broker и Terraform в Unix/Linux

Работа с AWS EFS и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с AWS elasticache и Terraform в Unix/Linux» завершена.


Установка Kubernetes в Unix/Linux

$
0
0

Установка Kubernetes в Unix/Linux

Kubernetes — это предназначенный для контейнерной оркестровки фреймворк с открытым исходным кодом. Он был создан с учетом богатейшего опыта Google в области создания сред управления контейнерами и позволяет выполнять контейнеризованные приложения в готовом к промышленной эксплуатации кластере.

Разработанный на тех же принципах, что позволяет Google запускать миллиарды контейнеров в неделю, Kubernetes может масштабироваться без увеличения вашей команды ops.

Независимо от того, тестируете ли вы локально или работает с PROD, гибкость Kubernetes растет с вами, чтобы обеспечить бесперебойную доставку ваших приложений независимо от сложности вашей потребностей.

Kubernetes — предоставляет вам свободу использовать инфраструктуру на местах, гибридную или общественную облачную инфраструктуру, позволяя вам легко перемещать рабочие нагрузки туда, где это важно.

Концепции Kubernetes

  • Nodes (node.md): Нода это машина в кластере Kubernetes.
  • Pods (pods.md): Pod это группа контейнеров с общими разделами, запускаемых как единое целое.
  • Replication Controllers (replication-controller.md): replication controller гарантирует, что определенное количество «реплик» pod’ы будут запущены в любой момент времени.
  • Services (services.md): Сервис в Kubernetes это абстракция которая определяет логический объединённый набор pod и политику доступа к ним.
  • Volumes (volumes.md): Volume(раздел) это директория, возможно, с данными в ней, которая доступна в контейнере.
  • Labels (labels.md): Label’ы это пары ключ/значение которые прикрепляются к объектам, например pod’ам. Label’ы могут быть использованы для создания и выбора наборов объектов.
  • Kubectl Command Line Interface (kubectl.md): kubectl интерфейс командной строки для управления Kubernetes.

Архитектура Kubernetes

Работающий кластер Kubernetes включает в себя агента, запущенного на нодах (kubelet) и компоненты мастера (APIs, scheduler, etc), поверх решения с распределённым хранилищем. Приведённая схема показывает желаемое, в конечном итоге, состояние, хотя все ещё ведётся работа над некоторыми вещами, например: как сделать так, чтобы kubelet (все компоненты, на самом деле) самостоятельно запускался в контейнере, что сделает планировщик на 100% подключаемым.

Архитектура Kubernetes

Архитектура Kubernete

Нода Kubernetes

При взгляде на архитектуру системы мы можем разбить его на сервисы, которые работают на каждой ноде и сервисы уровня управления кластера. На каждой ноде Kubernetes запускаются сервисы, необходимые для управления нодой со стороны мастера и для запуска приложений. Конечно, на каждой ноде запускается Docker. Docker обеспечивает загрузку образов и запуск контейнеров.

Kubelet

Kubelet управляет pod’ами их контейнерами, образами, разделами, etc.

Kube-Proxy

Также на каждой ноде запускается простой proxy-балансировщик. Этот сервис запускается на каждой ноде и настраивается в Kubernetes API. Kube-Proxy может выполнять простейшее перенаправление потоков TCP и UDP (round robin) между набором бэкендов.

Компоненты управления Kubernetes

Система управления Kubernetes разделена на несколько компонентов. В данный момент все они запускаются на мастер-ноде, но в скором времени это будет изменено для возможности создания отказоустойчивого кластера. Эти компоненты работают вместе, чтобы обеспечить единое представление кластера.

etcd

Состояние мастера хранится в экземпляре etcd. Это обеспечивает надёжное хранение конфигурационных данных и своевременное оповещение прочих компонентов об изменении состояния.

Kubernetes API Server

Kubernetes API обеспечивает работу api-сервера. Он предназначен для того, чтобы быть CRUD сервером со встроенной бизнес-логикой, реализованной в отдельных компонентах или в плагинах. Он, в основном, обрабатывает REST операции, проверяя их и обновляя соответствующие объекты в etcd (и событийно в других хранилищах).

Scheduler

Scheduler привязывает незапущенные pod’ы к нодам через вызов /binding API. Scheduler подключаем; планируется поддержка множественных scheduler’ов и пользовательских scheduler’ов.

Kubernetes Controller Manager Server

Все остальные функции уровня кластера представлены в Controller Manager. Например, ноды обнаруживаются, управляются и контролируются средствами node controller. Эта сущность в итоге может быть разделена на отдельные компоненты, чтобы сделать их независимо подключаемыми.

ReplicationController — это механизм, основывающийся на pod API. В конечном счете планируется перевести её на общий механизм plug-in, когда он будет реализован.

Сеть в kubernetes

Flannel — сетевой оверлей, который позволит контейнерам связываться через несколько хостов.

Calico — это система с открытым исходным кодом, обеспечивающая взаимодействие с облачными приложениями и политикой.

Canal — это инициатива, основанная на сообществах, которая позволяет пользователям легко развертывать сети Calico и flannel вместе (как единое сетевое решение), сочетающее в себе ведущие в отрасли сетевые политики Calico с богатым набором опций Calico и фланцевого наложения и опциями без подключения к сети.

Kube-route — построен вокруг концепции наблюдателей и контроллеров. Наблюдатели используют API-интерфейс Kubernetes для получения уведомлений о событиях, связанных с созданием, обновлением и удалением объектов Kubernetes. Каждый наблюдатель получает уведомление, относящееся к определенному объекту API. При получении события от сервера API наблюдатель передает события. Контроллер регистрируется, чтобы получать обновления от наблюдателей и действовать на события.

Romana — это решение для автоматизации сетей и безопасности для облачных приложений. Romana автоматизирует создание изолированных облачных сетей, защищает приложения, использующие микросегментацию, и применяет политики контроля доступа на всех конечных точках, где бы они ни запускались.

Weave Net — еще одно решение для реализации сети в Kubernetes с поддержкой CNI.

Установка Kubernetes в Unix/Linux

Для работы с кубернетисом, нужен — докер (Ого — нежданчик! Да? 🙂 ). Начнем с установки docker-а, у меня уже имеется документация по этому можете ознакомится тут:

Установка Docker на Debian/Ubuntu

Установка Docker на CentOS/RedHat/Fedora

Вспомогательная информация, возможно — будет полезна:

Установка docker-compose в Unix/Linux

Создание docker с nginx + lua на CentOS7

Создание docker контейнера в Unix/Linux

Остановить/Удалить все Docker контейнеры/images

Ну что, перейдем к установке самого кубирнетиса…

Установка Kubernetes в CenOS/Fedora/RedHat

В настройке Kubernetes у нас есть главный узел (master) и дочерние узлы (minions). Для управления кластером (мастером и миньенами) можно используя команды «kubeadm» и «kubectl».

Kubernetes можно установить и развернуть, используя следующие методы:

  • Minikube (это единичный кластер — single node kubernetes cluster).
  • Kops (настройка нескольких серверов (Multi node kubernetes) в AWS)
  • Kubeadm (кластер Multi Node в наших собственных помещениях)

Для примера, я возьму три сервера ( Пример: CentOS с минимальной установкой). Один сервер будет работать как мастер, а остальные два сервера — будут миньонами или рабочими узлами. Диаграмма будет такая:

Kubernetes диаграмма

На главном узле (он же мастер) будут установлены следующие компоненты:

  • API Server, Scheduler, Controller Manager, etcd, Kubectl utility — Описание данных сервисов/служб, я описывал выше.

На рабочих узлах (они же миньйоны) будут установлены следующие компоненты:

  • Kubelet, Kube-Proxy, Pod — Описание данных сервисов/служб, я описывал выше.

Установка и настройка kubernetes master ноды в CentOS

Начем с того, что выключим SELinux — у меня есть статья Как отключить SELinux на CentOS но для выстроты, я все таки напишу команды:

# setenforce 0 && sed -i --follow-symlinks 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux

Так же, если используете фаервол, то стоит пробросить порты (пример для CentOS 7):

 # firewall-cmd --permanent --add-port=6443/tcp
 # firewall-cmd --permanent --add-port=2379-2380/tcp
 # firewall-cmd --permanent --add-port=10250/tcp
 # firewall-cmd --permanent --add-port=10251/tcp
 # firewall-cmd --permanent --add-port=10252/tcp
 # firewall-cmd --permanent --add-port=10255/tcp
 # firewall-cmd --reload
 # modprobe br_netfilter
 # echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables

PS: Можно выключить службу:

# systemctl stop firewalld.service

ИЛИ:

$ systemctl stop firewalld && systemctl disable firewalld

Так же, я хотел бы отметить то, что кубик не поддерживает SWAP. По этому, его можно проигнорировать или выключить вообще (swapoff -a).

Не забываем о том, что если вы не юзаете DNS сервер, то стоит прописать /etc/hosts файл все ваши хосты, например:

# bash -c 'cat <> /etc/hosts
192.168.13.10 master
192.168.13.20 node-1
192.168.13.30 node-2
EOF'

Скачаем утилиту kubectl (на момент написания статьи, использовалась самая новая версия ПО):

# curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl

Перенесем файл:

$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl

Добавим репозиторий с kubernetes:

# cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

Собственно, выполняем установку:

# yum install kubeadm etcd -y

Добавялем службу в автозагрузку ОС и запускаем сервис:

# systemctl enable kubelet && systemctl restart kubelet

Так же, стоит запустить докер!

На какой-то ноде получил ошибку:

Mar  2 13:02:31 localhost systemd: kubelet.service holdoff time over, scheduling restart.
Mar  2 13:02:31 localhost systemd: Started kubelet: The Kubernetes Node Agent.
Mar  2 13:02:31 localhost systemd: Starting kubelet: The Kubernetes Node Agent...
Mar  2 13:02:31 localhost kubelet: I0302 13:02:31.294420    1907 feature_gate.go:226] feature gates: &{{} map[]}
Mar  2 13:02:31 localhost kubelet: I0302 13:02:31.294496    1907 controller.go:114] kubelet config controller: starting controller
Mar  2 13:02:31 localhost kubelet: I0302 13:02:31.294500    1907 controller.go:118] kubelet config controller: validating combination of defaults and flags
Mar  2 13:02:31 localhost kubelet: error: unable to load client CA file /etc/kubernetes/pki/ca.crt: open /etc/kubernetes/pki/ca.crt: no such file or directory
Mar  2 13:02:31 localhost systemd: kubelet.service: main process exited, code=exited, status=1/FAILURE
Mar  2 13:02:31 localhost systemd: Unit kubelet.service entered failed state.
Mar  2 13:02:31 localhost systemd: kubelet.service failed.

Решение:

# kubeadm reset && systemctl restart kubelet && kubeadm init --skip-preflight-checks --pod-network-cidr=10.244.0.0/16

Собственно, можно пропустить данный фикс. Оно исправится с инициализацией кластера…..

Запустите команду чтобы инициализировать и настроить kubernetes мастер ноду:

# kubeadm init

Примерный вывод:

[init] Using Kubernetes version: v1.9.3
[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks.
	[WARNING FileExisting-crictl]: crictl not found in system path
[certificates] Generated ca certificate and key.
[certificates] Generated apiserver certificate and key.
[certificates] apiserver serving cert is signed for DNS names [localhost.localdomain kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.13.219]
[certificates] Generated apiserver-kubelet-client certificate and key.
[certificates] Generated sa key and public key.
[certificates] Generated front-proxy-ca certificate and key.
[certificates] Generated front-proxy-client certificate and key.
[certificates] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[kubeconfig] Wrote KubeConfig file to disk: "admin.conf"
[kubeconfig] Wrote KubeConfig file to disk: "kubelet.conf"
[kubeconfig] Wrote KubeConfig file to disk: "controller-manager.conf"
[kubeconfig] Wrote KubeConfig file to disk: "scheduler.conf"
[controlplane] Wrote Static Pod manifest for component kube-apiserver to "/etc/kubernetes/manifests/kube-apiserver.yaml"
[controlplane] Wrote Static Pod manifest for component kube-controller-manager to "/etc/kubernetes/manifests/kube-controller-manager.yaml"
[controlplane] Wrote Static Pod manifest for component kube-scheduler to "/etc/kubernetes/manifests/kube-scheduler.yaml"
[etcd] Wrote Static Pod manifest for a local etcd instance to "/etc/kubernetes/manifests/etcd.yaml"
[init] Waiting for the kubelet to boot up the control plane as Static Pods from directory "/etc/kubernetes/manifests".
[init] This might take a minute or longer if the control plane images have to be pulled.
[apiclient] All control plane components are healthy after 49.503153 seconds
[uploadconfig] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[markmaster] Will mark node localhost.localdomain as master by adding a label and a taint
[markmaster] Master localhost.localdomain tainted and labelled with key/value: node-role.kubernetes.io/master=""
[bootstraptoken] Using token: b8e1bf.c8828a7e32947b5e
[bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: kube-dns
[addons] Applied essential addon: kube-proxy

Your Kubernetes master has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join --token b8e1bf.c8828a7e32947b5e 192.168.13.219:6443 --discovery-token-ca-cert-hash sha256:2b17b03e16e2a0459abdd05b191abf8c444b264b2f4fe28d44ae2ff6ab7b1837

Внизу имеется токен, он нам понадобится немного позже (когда будем добавлять ноды в кластер). Сохраните его! Если забыли или упустили токен, можно посмотреть токены:

# kubeadm token list
TOKEN                     TTL       EXPIRES                     USAGES                   DESCRIPTION                                                EXTRA GROUPS
c732da.2ee47aa3370b4460   23h       2018-03-03T13:03:19+02:00   authentication,signing   The default bootstrap token generated by 'kubeadm init'.   system:bootstrappers:kubeadm:default-node-token

Для генерации токена, можно использовать:

# kubeadm token generate
2d4041.f36eaef929570488

Для использования сгенерированного токена, служит команда:

# kubeadm token create 2d4041.f36eaef929570488 --print-join-command --ttl=0

Удаляем токен так:

# kubeadm token delete 2d4041.f36eaef929570488

bootstrap token with id "2d4041" deleted

Чтобы сбросить все настройки, используйте:

# kubeadm reset

PS: Так же, можно использовать:

$ sudo kubeadm init --apiserver-advertise-address=192.168.13.10 --pod-network-cidr=10.244.0.0/16

Где:

  • —apiserver-advertise-address=192.168.13.10  — явно указывает мастеру на IP адрес, который нужно сообщать клиентам для подключения
  • —pod-network-cidr=10.244.0.0/16 используется для установки адресного пространства для ваших pod-ов в flannel.

Сейчас стоит выполнить настройку для запуска кластера от определенного пользователя:

# mkdir -p $HOME/.kube && cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && chown $(id -u):$(id -g) $HOME/.kube/config

PS: У меня это будет пользователь — root. Но для удобства использования, можно создать отдельного юзера, например — kubernetes и выставить права на него:

# adduser kubernetes
# passwd kubernetes
# usermod -aG wheel kubernetes
# su - kubernetes

Сейчас, нужно настроить pod network для кластера:

# kubectl get nodes

С самого начала, — сеть будет не доступна. Выполним еще проверку:

# kubectl get pods --all-namespaces

Чтобы статус кластера был готов (Было все настроено и так же, имел kube-dns status — running , разверните сеть контейнера, чтобы контейнеры разных хостов обменивались друг с другом. Сеть POD представляет собой оверлейную сеть между рабочими узлами. Запустите команду для развертывания сети:

# export kubever=$(kubectl version | base64 | tr -d '\n')
# kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$kubever"
serviceaccount "weave-net" created
clusterrole "weave-net" created
clusterrolebinding "weave-net" created
daemonset "weave-net" created

Различные сети поддерживаются в k8s и зависят от выбора пользователя. Хочу привести еще один пример с сетью, который использует RBAC (Role Based Access Control), поэтому убедитесь, что сеть, которую вы собираетесь использовать, поддерживает RBAC (не проверял работу этого сетевого интерфейса):

# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel-rbac.yml

Думаю что уже все будет работать, но стоит перепроверить это еще 1 раз:

# kubectl get nodes && kubectl  get pods --all-namespaces

Чтобы получить больше полезной информации, выполните:

$ kubectl get pods –all-namespaces -o wide

Поздравляю, — мастер готов!

Установка и настройка kubernetes миньйонов в CentOS

Начем с того, что выключим SELinux — у меня есть статья Как отключить SELinux на CentOS но для выстроты, я все таки напишу команды:

# setenforce 0 && sed -i --follow-symlinks 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux

Так же, если используете фаервол, то стоит пробросить порты (пример для CentOS 7):

# firewall-cmd --permanent --add-port=10250/tcp
# firewall-cmd --permanent --add-port=10255/tcp
# firewall-cmd --permanent --add-port=30000-32767/tcp
# firewall-cmd --permanent --add-port=6783/tcp
# firewall-cmd  --reload
# echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables

Не забываем о том, что если вы не юзаете DNS сервер, то стоит прописать /etc/hosts файл все ваши хосты.

Добавим репозиторий:

# cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

Собственно, выполняем установку (на всех воркерах или миньйонах):

# yum install kubeadm -y

PS: Добавляем докер в автозагрузку ОС и запускаем его!

Добавляем миньйоны в kubernetis kluster (мастер):

# kubeadm join --token KUBERNETES_MASTER_TOKEN KUBERNETES_MASTER_IP:6443

Где:

  • KUBERNETES_MASTER_TOKEN — Это токен, который служит для добавления рабочих нод в кластер.
  • KUBERNETES_MASTER_IP — Это IP самого кубернетес мастер ноды.
  • 6443 — Порт от мастер-ноды.

Для проверки работоспообности созданного кластера, выполним:

# kubectl get nodes

Для автодополнения команд, можно выполнить следующее:

$ echo "source <(kubectl completion bash)" >> ~/.bashrc

Как-то так!

Установка Kubernetes в Debian

Ставим зависимости:

# apt-get install gcc golang-go curl git apt-transport-https

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

# curl -L https://github.com/coreos/etcd/releases/download/v2.0.3/etcd-v2.0.3-linux-amd64.tar.gz -o etcd-v2.0.3-linux-amd64.tar.gz && tar xzvf etcd-v2.0.3-linux-amd64.tar.gz && cd etcd-v2.0.3-linux-amd64

Копируем бинарник:

# cp etcd /usr/bin/etcd

Ставим права:

# chmod +x /usr/bin/etcd

Скачиваем и компилируем сам кубик:

# cd /usr/local/src && git clone https://github.com/GoogleCloudPlatform/kubernetes.git
# cd kubernetes && make release

В папке с кубернетесом появятся скрипты для работы с кластером, нодами. Например:

#  hack/local-up-cluster.sh

Для автодополнения команд, можно выполнить следующее:

$ echo "source <(kubectl completion bash)" >> ~/.bashrc

Как-то так!

Установка Kubernetes в Ubuntu

Нужно обновить ОС, и установить вспомогательные пакеты:

# apt-get update && apt-get install -y apt-transport-https

Первый шаг — загрузить и добавить ключ для установки Kubernetes:

# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add

Открываем файл:

# vim  /etc/apt/sources.list.d/kubernetes.list

Прописываем в него:

deb http://apt.kubernetes.io/ kubernetes-xenial main

Сохраняем и закрываем файл. Выполняем установку Kubernetes:

# apt-get update && apt-get install -y kubelet kubeadm kubectl kubernetes-cni

Установка и настройка kubernetes мастера в Ubuntu

На мастер ноде, выполняем инициализацию кластера:

# kubeadm init

Прежде чем присоединить ноды в кластер, необходимо выпустить следующие команды (как обычный пользователь или при необходимости, создать нового юзверя):

# mkdir -p $HOME/.kube
# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# chown $(id -u):$(id -g) $HOME/.kube/config

Кластер уже инициализирован, нужно развернуть сеть:

# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/k8s-manifests/kube-flannel-rbac.yml

Проверим работоспособность клатера (до того как начнем добавлять ноды в кластер):

# kubectl get pods —all-namespaces

Установка и настройка kubernetes миньйонов в Ubuntu

Точно так же, ставим кубик… после чего, выполняем добавление нод:

# kubeadm join --token KUBERNETES_MASTER_TOKEN KUBERNETES_MASTER_IP:6443

Где:

  • KUBERNETES_MASTER_TOKEN — Это токен, который служит для добавления рабочих нод в кластер.
  • KUBERNETES_MASTER_IP — Это IP самого кубернетес мастер ноды.
  • 6443 — Порт от мастер-ноды.

На мастере, выполняем команду:

# kubectl get nodes

Более понятно было описано в пункте с установкой kubernetes-а для CentOS.

Для автодополнения команд, можно выполнить следующее:

$ echo "source <(kubectl completion bash)" >> ~/.bashrc

Как-то так!

Установка Kubernetes в Mac OS X

Существует пару способов установить кубик на MacOS X.

-=== СПОСОБ 1 — Использовать Docker Edge ===-

Скачиваем Docker Edge образ с официального сайта, нужно установить его (куда же без этого). Запускаем. Во вкладке «kubernetes» нужно включить данную функцию:

Установка Kubernetes в Mac OS X

Нажимаем на «Enable Kubernetes» и потом на «Install». Это запустит кластер Kubernetes для одного узла и установит kubectl утилиту. Это может занять некоторое время….

Через несколько минут, я вижу что у меня кубик запустился «Kubernetes is running» и можно приступить к использованию. Прежде чем продолжить: если вы ранее использовали kubectl, вам, возможно, придется переключить контекст на локальный кластер (local cluster). Выполните следующую команду:

# kubectl config use-context docker-for-desktop

Получаем вывод:

Switched to context "docker-for-desktop".

Нет смысла запускать кластер с kubernetes, если вы не будете с ним работать, не так ли? Начнем с того, что развернем пользовательский интерфейс панели управления Kubernetes, для этого стоит выполнить:

# kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

secret "kubernetes-dashboard-certs" created
serviceaccount "kubernetes-dashboard" created
role "kubernetes-dashboard-minimal" created
rolebinding "kubernetes-dashboard-minimal" created
deployment "kubernetes-dashboard" created
service "kubernetes-dashboard" created

Еще, потребуется запустить прокси:

# kubectl proxy

После этого, открываем:

http://127.0.0.1:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy

И, попадаем в меню первоначальной настройки. Я не стал ничего применять — нажал на «skip» чтобы пропустить. И собственно зашел в админ панель:

first workload на kubernetes

Что это за панель я еще и сам не понял. Но работает!

-=== СПОСОБ 2 — Использовать Homebrew ===-

Как оказалось потом, kubernetes можно установить и через brew. Для начала, стоит установить homebrew.

Выполняем установку Xyve Driver:

$ brew install docker-machine-driver-xhyve
# chown root:wheel $(brew --prefix)/opt/docker-machine-driver-xhyve/bin/docker-machine-driver-xhyve
# chmod u+s $(brew --prefix)/opt/docker-machine-driver-xhyve/bin/docker-machine-driver-xhyve

Выполняем установку Minikube:

$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64
# chmod +x minikube
# mv minikube /usr/local/bin/

Выполняем установку Kubectl:

$ brew install kubectl

Наконец, пришло время запустить Кубернетес. Ниже приведены две команды для запуска Minikube. Выполните следующую команду, чтобы проверить, имеете ли вы доступ к сайтам за прокси-сервером или нет:

$ curl --proxy "" https://cloud.google.com/container-registry/

No Proxy: Если вы не находитесь за прокси-сервером, выполните следующую команду:

$ minikube start --vm-driver=xhyve

Proxy: Выполните следующую команду, когда вы находитесь за прокси-сервером:

$ minikube start --vm-driver=xhyve --docker-env HTTP_PROXY=http://your-http-proxy-host:your-http-proxy-port  --docker-env HTTPS_PROXY=http(s)://your-https-proxy-host:your-https-proxy-port

Для запуска minikube используйте:

$ minikube start

Для остановки minikube используйте:

$ minikube stop

Выполните следующую команду для доступа к панели управления Kubernetes:

$ minikube dashboard

Открываем ссылку:

http://127.0.0.1:30000/#!/overview?namespace=default

Для автодополнения команд, можно выполнить следующее:

## If running Bash 3.2 included with macOS
$ brew install bash-completion
## or, if running Bash 4.1+
$ brew install bash-completion@2

Как-то так!

Использование Kubernetes в Unix/Linux

Ну что, готовы задеплоить службу на своем Kubernetes кластере? Возьму пример с nginx:

# kubectl run --image=nginx nginx-app --port=80 --env="DOMAIN=cluster"
# kubectl expose deployment nginx-app --port=80 --name=nginx-http

Если вы перейдете на ноду и выполните команду:

# docker ps -a

То вы увидите, что указанная служба запустилась на кластере. Я пока что не буду заострять внимание на деплое приложенек, все будет, но не сразу. 🙂 В новой теме, я расскажу как развернуть полноценный kubernetes кластер с «блэкджеком и куртизанками».

Возможно я не затронул какие-то моменты, но я на данную статью потратил довольно много времени. Если появится что дополнить, обязательно добавлю. При желании, любой желающий может помогать мне в этом.

Вот и все, статья «Установка Kubernetes в Unix/Linux» подошла к завершению.

Установка cgroups в Unix/Linux

$
0
0

Установка cgroups в Unix/Linux

cgroups (англ. control group) — механизм ядра Linux, который ограничивает и изолирует вычислительные ресурсы (процессорные, сетевые, ресурсы памяти, ресурсы ввода-вывода) для групп процессов. Механизм позволяет образовывать иерархические группы процессов с заданными ресурсными свойствами и обеспечивает программное управление ими.

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

Архитектура cgroups

Механизм cgroups состоит из двух составных частей: ядра (cgroup core) и так называемых подсистем.

  • net_cls — помечает сетевые пакеты специальным тэгом, что позволяет идентифицировать пакеты, порождаемые определённой задачей в рамках контрольной группы;
  • devices — разрешает или блокирует доступ к устройствам;
  • blkio — устанавливает лимиты на чтение и запись с блочных устройств;
  • pids — используется для ограничения количества процессов в рамках контрольной группы.
  • cpu — обеспечивает доступ процессов в рамках контрольной группы к CPU;
  • hugetlb — активирует поддержку больших страниц памяти для контрольных групп;
  • cpuacct — генерирует отчёты об использовании ресурсов процессора;
  • freezer — приостанавливает и возобновляет выполнение задач в рамках контрольной группы
  • cpuset — распределяет задачи в рамках контрольной группы между процессорными ядрами;
  • memory — управляет выделением памяти для групп процессов;
  • netprio — используется для динамической установки приоритетов по трафику;

Установка cgroups в Unix/Linux

Данная тема охватит несколько ОС с наглядными примерами.

Установка cgroups в CentOS/RedHat

Данные управляющие группы и подсистемы ( к которым они относятся), могут управляться с помощью shell команд и утилит. Однако самый простой способ работы с такими группами — установить пакет libcgroup. Чтобы установить его, выполните следующую команду:

# yum install libcgroup -y

Служба cgconfig (конфигурация группы управления) используется для создания групп и управления подсистемами. Данный сервис может быть настроен для запуска во время загрузки и восстановления предустановленных групп, что делает их постоянными при перезагрузках. Чтобы запустить cgconfig  службы, выполните:

# service cgconfig start

Для проверки статуса, можно выполнить:

# service cgconfig status
Running

Чтобы добавить службу в автозагрузку ОС, выполните:

# chkconfig cgconfig on

Установка cgroups в Gentoo

Команда для установки:

$ su -c 'emerge libCGroup'

Установка cgroups в Fedora

Команда для установки:

$ su -c 'yum -y install libCGroup-tools'

Установка cgroups в Debian/Ubuntu

Не было необходимости еще!

Настройка cgroups в Unix/Linux

Документация ядра предоставляет общее описание с примерами. Но я в своей статье «Установка cgroups в Unix/Linux» опишу все возможные примеры максимально подробно.

Пакет cgroups-bin (который зависит от libcgroup1), уже предоставленный дистрибутивом. Настройка выполняется путем редактирования следующих двух файлов:

  • /etc/cgconfig.conf — В зависимости от содержимого файла конфигурации cgconfig может создавать иерархии, монтировать необходимые файловые системы, создавать группы и устанавливать параметры подсистемы (ограничения ресурсов) для каждой группы. Иерархия представляет собой набор групп, расположенных в дереве, так что каждая задача в системе находится в одной из групп в иерархии.
  • /etc/cgrules.conf — Служит для добавления ограничений для пользователей, групп, процессов.

Менеджер рабочей нагрузки (cgconfig) отвечает за распределение ресурсов.

Добавление нового процесса в менеджер можно следующим образом:

# cgexec [-g <controllers>:<path>] command [args]

Добавление уже запущенного процесса в менеджер:

# cgclassify [-g <controllers>:<path>] <pidlist>

Или, можно использовать автоматический режим при работе с файлом cgrules.conf и CGroup Rules Daemon (cgred), который заставляет каждый вновь созданный процесс использовать ограничение по группе (но об этом позже).

И так, начнем редактирование:

# vim /etc/cgconfig.conf

Вот пример моего:

group group1 {
        perm {
                task {
                        uid = captain;
                        gid = captain;
                }
                admin {
                        uid = root;
                        gid = root;
                }
        }

        cpu {
                cpu.shares = 500;
        }
}

group limitcpu{
        cpu {
                cpu.shares = 400;
        }
}

group limitmem{
        memory {
                memory.limit_in_bytes = 512m;
        }
}
group limitio{
        blkio {
                blkio.throttle.read_bps_device = "11:0 2097152";
        }
}
group browsers{
        cpu {
                cpu.shares = 200;
        }
        memory {
                memory.limit_in_bytes = 128m;
        }
}

Можно этот файл использовать а можно создать новый файл в /etc/cgconfig.d директории, например:

# vim /etc/cgconfig.d/test.conf

Пояснения:

  • В группе limitcpu ограничиваем общие ресурсы cpu доступными для процессов в этой группе до 400. cpu.shares указывает относительную долю времени процессора, доступного для задач в cgroup.
  • В группе limitmem ограничиваем доступную памяти cgroup процессам до 512 МБ.
  • В limitio группе ограничиваем пропускную способность диска до 2 Мбайт/с. Здесь ограничиваем чтение ввода-вывода на основной диск, /dev/vda, с основным: младший номер 11:0 и 2MiB/s преобразуется в байты в секунду (2x1024x1024 = 2097152).
  • В browsers группе ограничиваем общие ресурсы процессора до 200 и доступную память до 128 МБ.

Затем убедитесь, что настроенные группы отображаются правильно:

# lscgroup
cpuset:/
cpu:/
cpu:/browsers
cpu:/limitcpu
cpu:/group1
cpuacct:/
memory:/
memory:/browsers
memory:/limitmem
devices:/
freezer:/
net_cls:/
blkio:/
blkio:/limitio

Наша следующая цель — добавить процессы (задачи), для которых мы хотим ограничить ресурсы для ранее созданных групп. Cgred (механизм управления группами) — это служба, которая перемещает задачи в группы в соответствии с параметрами, заданными в файле /etc/cgrules.conf. Записи в файле /etc/cgrules.conf могут принимать одну из двух форм:

user subsystems control_group

ИЛИ:

user:command subsystems control_group

user ссылается на имя пользователя или имя группы с префиксом «@». Подсистемы (subsystems) относятся к списку подсистем, которые разделенному запятыми. control_group представляет собой путь к cgroup, а команда обозначает имя процесса или полный путь к процессу процесса. Записи в файле /etc/cgrules.conf могут содержать следующие дополнительные обозначения:

  • @ — Указывает группу вместо отдельного пользователя. Например, @admin указывает всех пользователей в admin группе.
  • * — Использовать «все\всех». Например, если установить * в user поле, то это будет говорить, что будут использоватся все пользователи в ОС.
  • % — Представляет элемент тот же, что и элемент в строке выше.

Теперь добавим ограничение к программам/процессам, которые хотим ограничить, открываем:

# vim /etc/cgrules.conf

И прописываем:

captain cpu group1/
*:firefox cpu,memory browsers/
*:hdparm blkio limitio/
sammy blkio limitio/
@admin:memhog memory limitmem/
*:cpuhog cpu limitcpu/

В приведенных выше строках устанавливаем следующие правила:

  • Для пользователя (captain) ограничиваем CPU.  Для этого, ему назначаем group1 группу.
  • Процессы firefox запускаемые от любого пользователя, будут автоматически добавлены в browsers группу и ограничеваем в подсистеме CPU и RAM.
  • Процессы hdparm запускаемые от любого пользователя, будут добавленs в blkio группу с ограничением подсистемы blkio в соответствии с значениями параметров, указанными в этой группе.
  • Все процессы, выполняемые пользователем sammy, будут добавлены в лимитированную группу и ограничены в подсистеме blkio.
  • Процессы memhog, запускаемые кем-либо из группы admin, будут добавлены в limitmem cgroup и ограничены по памяти.
  • Процессы cpuhog, выполняемые от любого пользователя, будут добавлены в limitcpu группу и ограничены по CPU.

Нам нужно запустить/перезапустить cgred-службу, чтобы изменения конфигурации cgrules вступили в силу, сделайте это, используя команду:

# service cgred restart

Нам также необходимо убедиться, что служба cgred включена для запуска при атозагрузке системы, чтобы наши правила сохранялись при перезагрузке:

# chkconfig cgred on

ЗАМЕЧАНИЕ: Для служб, которые поддерживают sysconfig, вы можете добавить CGROUP_DAEMON=»subsystem:control_group» переменную  в /etc/sysconfig/servicename вместо редактирования файла cgrules.conf. Например, для httpd службы, вы можете добавить CGROUP_DAEMON=»blkio:/limitio» в файл /etc/sysconfig/httpd.conf, чтобы добавить httpd-процессы в группу limitio.

Затем перезапустите:

# service cgconfig restart

Настройка завершена.

Использование, тестирование cgroups в Unix/Linux

Запуск службы cgconfig создает виртуальную файловую систему, установленную в /cgroup со всеми подсистемами. Проверим это:

# ls /cgroup

Получаем следующие подсистемы:

blkio cpu cpuacct cpuset devices freezer memory net_cls

Можно запустить команду `lscgroup ‘для проверки:

$ sudo lscgroup

Вы увидите подсистемы в несколько иной компоновке:

cpuset:/
cpu:/
cpuacct:/
memory:/
devices:/
freezer:/
net_cls:/
blkio:/

Протестируем ограничение на диск, для этого — нужно установить утилиту hdparm. Например, для rpm’s ОС, выполните:

# yum install hdparm

Теперь давайте запустим команду для измерения скорости чтения вашего жесткого диска, например:

# hdparm --direct -t /dev/vda

Вывод будет такой:

/dev/vda:
Timing O_DIRECT disk reads: 6 MB in 3.00 seconds = 2.00 MB/sec

На выходе показана пропускная способность диска 2 МБ/с. Если вы остановите службы cgconfig и cgred и снова запустите команду hdparm, вы можете увидеть исходную/стандартную скорость чтения с того момента, когда правила группы не были реализованы.

Создание cgroups в Unix/Linux

Чтобы создать CGroup c ограничением по CPU/RAM, выполним:

# cgcreate -g cpu,memory:your_cgroup_name

Где:

  • cpu,memory — Какие ресурсы будут ограничены. Можно еще ограничить — cpuset,cpuacct.
  • your_cgroup_name — Название вашей cgroup группы.

Можно установить ограничение прям в консоле, например, — установим ограничение по использованию RAM:

# cgset -r memory.limit_in_bytes=1G your_cgroup_name

Можно установить ограничение прям в консоле, например, — установим ограничение по использованию CPU приоритет до ~10% (1024 — это 100% приоритет):

# cgset -r cpu.shares=102 your_cgroup_name

Если используете systemD, то можно использовать SystemD Slices, нпример:

# systemctl set-property user.slice MemoryLimit=512M
# systemctl set-property system.slice MemoryLimit=1024M

Или, можно закинуть в fstab:

# cat /etc/fstab | grep -E "cgroup"

cgroup /sys/fs/cgroup cgroup defaults 0 0

Мне этого хватило что-бы пофиксить кое-что связанное с докером. Если появятся мысли что дополнить — обязательно дополню. Вот и все, статья «Установка cgroups в Unix/Linux» завершена.

Установка Kubernetes кластера в Unix/Linux

$
0
0

Установка Kubernetes кластера в Unix/Linux

Kubernetes (часто так же используется обозначение «K8s», название образовано от греческого κυβερνήτης, — «кормчий»,»рулевой», по русски — Кубернетес или Кубернетис) — открытое программное обеспечение для автоматизации развёртывания, масштабирования и управления контейнеризированными приложениями. Оригинальная версия была разработана компанией Google. Впоследствии Kubernetes был передан под управление Cloud Native Computing Foundation. Предназначение Kubernetes — предоставить «платформу для автоматического развёртывания, масштабирования, управления приложениями на кластерах или отдельных хостах». Кубернетис поддерживает различные технологии контейнеризации, включая Docker, VMWare и ряд других.

Kenernetes используется фондом Wikimedia Foundation, инфраструктура которого мигрировала на это приложение с самостоятельно разработанного ПО для организации кластеров.

Установка Kubernetes кластера в Unix/Linux

Я рассказывал об установке kubernetes-а ранее в моей статье, — Установка Kubernetes в Unix/Linux. По этому — я немного опущу установку ПО и расскажу как можно собрать полноценный кластер с «блэкджеком и куртизанками», т.е — собрать все воедино. Добавлять автоматически ноды, мониторить их и так же — выполнять деплой приложений, скейлинг в зависимости от нужд.

И так дано:

  • 192.168.13.219 — Нода kubernetes-master-1 на CentOS 7.
  • 192.168.13.230 — Нода kubernetes-worker-1 наDebian 8.
  • 192.168.13.147 — Нода kubernetes-worker-2 на Debian 8.

Кластерная диаграмма  кубернетес кластера, выглядит следующим образом:

Кластерная диаграмма  кубернетес кластера

  • Мастер отвечает за управление кластером. Master узлы будут координировать всю деятельность, происходящую в вашем кластере, например, приложения для планирования, сохранение желаемого состояния, масштабирование приложений и обновление апликейщенов.
  • Узел (node) представляет собой виртуальную машину или физический компьютер, который используется в качестве рабочего компьютера в кластере Kubernetes. Каждый узел из кластера управляется мастером. На типичном узле вы будете иметь инструменты для обработки операций с контейнерами (например, Docker, rkt) и Kubelet, агента для управления узлом. Кластер Kubernetes, который обрабатывает ПРОД, должен иметь минимум три узла в кластере.

Когда мы развертываем приложения на Kubernetes, мы говорим мастеру, чтобы он запускал контейнеры и планировал их запуск на других нодах. Связь между мстером и воркерами(нодами) осуществляется через API — мастером. Тот же API доступен для пользователей, чтобы облегчить взаимодействие с кластером.

Хватит теории, перейдем к установке и настройке самого кластера!

Установка kubernetes-master-1 на CentOS 7

Установлю хостнейм:

# hostnamectl set-hostname kubernetes-master-1

Это не столь важно, но для примера — будет красиво!

Т.к у меня нет DNS-сервера (я строю кластер локально, на виртуальных машинах), то нужно прописать:

# vim /etc/hosts

Следующее:

192.168.13.219 kubernetes-master-1
192.168.13.233 kubernetes-worker-1
192.168.13.234 kubernetes-worker-2

Это поможет резолвить ноды между собой.

Обновлю ОС:

# yum update -y && yum upgrade -y

Не забываем выключить SELinux,  а то он может наломать вам дров:

# setenforce 0 && sed -i --follow-symlinks 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux

Как вы знаете, в centOS 7 имеется firewalld и по этому — стоит пробрасывать правила (но в моем случае — нету смысла) или просто выключить его:

# systemctl stop firewalld && systemctl disable firewalld

Добавим репозиторий с kubernetes:

# cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

Собственно, выполняем установку докера и кубика:

# yum install docker kubectl kubeadm etcd ebtables ethtool -y

Добавялем докер-службу в автозагрузку ОС и запускаем сервис:

# systemctl enable docker && systemctl restart docker

Some users on RHEL/CentOS 7 have reported issues with traffic being routed incorrectly due to iptables being bypassed. You should ensure net.bridge.bridge-nf-call-iptables is set to 1 in your sysctl config, e.g.

# cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

и применяем:

# sysctl --system

Насчет etcd, я не уверен что нужно сувать его в автозагрузку ОС. Но можно это сделать вот так:

# systemctl enable etcd && systemctl restart etcd

Инициализируем мастер:

# kubeadm init --ignore-preflight-errors=all --pod-network-cidr=10.244.0.0/16

Где:

  • kubeadm init — Инициализируем кубернетес.
  • —ignore-preflight-errors=all — Скипаю все ошибки (но лучше не использовать этот параметр если не уверены).
  • —pod-network-cidr=10.244.0.0/16 — Задаем подсеть для будущего кубо-кластера (не обязательная опция).
  • —apiserver-advertise-address=192.168.13.231 — Можно задать данный параметр для установки IP адреса самого API сервера (не обязательная опция).
  • —kubernetes-version $(kubeadm version -o short) — Чтобы задать версию кубика (не обязательная опция).
  • —token=YOUR_TOKEN — Используется чтобы задать токен (не обязательная опция).

Добавялем кубернетес-службу в автозагрузку ОС и запускаем сервис:

# systemctl enable kubelet

Я не буду добавлять пользователя для кубика, буду использовать — root. Вносим изменения небольшие:

# mkdir -p $HOME/.kube
# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# chown $(id -u):$(id -g) $HOME/.kube/config

Так же, незабываем сохранить команду для добавления нод в мастер, у меня это:

# kubeadm join --token 86669e.c66ab92be6dc5817 192.168.13.219:6443 --discovery-token-ca-cert-hash sha256:f8905cc439b0498eeb3a0de4bf7937640c96cb7063a2bc99f917433a994c4559

Смотрим что вышло:

# kubectl get nodes
NAME                  STATUS     ROLES     AGE       VERSION
kubernetes-master-1   NotReady   master    4m        v1.9.3

PS: Можно получить следующую ошибку:

Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")

Решил:

# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && chown $(id -u):$(id -g) $HOME/.kube/config

Как видим, у меня — уже просетапался кубик-мастер нода. Но статус не готов, смотрим что не так:

# kubectl get pods --all-namespaces

NAMESPACE     NAME                                          READY     STATUS    RESTARTS   AGE
kube-system   etcd-kubernetes-master-1                      1/1       Running   0          27m
kube-system   kube-apiserver-kubernetes-master-1            1/1       Running   0          27m
kube-system   kube-controller-manager-kubernetes-master-1   1/1       Running   0          28m
kube-system   kube-dns-6f4fd4bdf-rtkjt                      0/3       Pending   0          28m
kube-system   kube-proxy-vs44m                              1/1       Running   0          28m
kube-system   kube-scheduler-kubernetes-master-1            1/1       Running   0          27m

Такс, нет DNS резолвера, — фиксаем:

# export kubever=$(kubectl version | base64 | tr -d '\n')
# kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$kubever"
serviceaccount "weave-net" created
clusterrole "weave-net" created
clusterrolebinding "weave-net" created
daemonset "weave-net" created

Различные сети поддерживаются в k8s и зависят от выбора пользователя. Создание сети, занимает определенное время (пару минут точно), через время — проверяем:

[root@kubernetes-master-1 ~]# kubectl get nodes && kubectl  get pods --all-namespaces
NAME                  STATUS    ROLES     AGE       VERSION
kubernetes-master-1   Ready     master    33m       v1.9.3
NAMESPACE     NAME                                          READY     STATUS              RESTARTS   AGE
kube-system   etcd-kubernetes-master-1                      1/1       Running             0          32m
kube-system   kube-apiserver-kubernetes-master-1            1/1       Running             0          32m
kube-system   kube-controller-manager-kubernetes-master-1   1/1       Running             0          32m
kube-system   kube-dns-6f4fd4bdf-rtkjt                      0/3       ContainerCreating   0          32m
kube-system   kube-proxy-vs44m                              1/1       Running             0          32m
kube-system   kube-scheduler-kubernetes-master-1            1/1       Running             0          32m
kube-system   weave-net-pzpxk                               2/2       Running             0          45s
[root@kubernetes-master-1 ~]#

Идем дальше — необходимо установить и добавить воркеры в созданный мастер!

Установка kubernetes-worker-1 на Debian 8

Установлю хостнейм:

# hostname kubernetes-worker-1

Это не столь важно, но для примера — будет красиво!

Т.к у меня нет DNS-сервера (я строю кластер локально, на виртуальных машинах), то нужно прописать:

# vim /etc/hosts

Следующее:

192.168.13.219 kubernetes-master-1
192.168.13.233 kubernetes-worker-1
192.168.13.234 kubernetes-worker-2

Это поможет резолвить ноды между собой.

Ставим нужные зависимости:

# apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

Устанавливаем докер:

# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository \
"deb https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
$(lsb_release -cs) \
stable"

Этой командой, добавляем репку, и для установки — выполняем:

# apt-get update && apt-get install -y docker-ce=$(apt-cache madison docker-ce | grep 17.03 | head -1 | awk '{print $3}')

Добавляем докер в автозагрузку ОС, запускаем его и смотрим статус:

# systemctl start docker && systemctl enable docker && systemctl status docker

Добавляем ключ:

# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -

Прописываем репо-лист:

# cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF

Сейчас, ставим кубик:

# apt-get update && apt-get install -y kubelet kubeadm kubectl

Добавляем kubelet в автозагрузку ОС, запускаем его и смотрим статус:

# systemctl start kubelet && systemctl enable kubelet && systemctl status kubelet

Все готово, можно добавлять ноду в кластер:

# kubeadm join --token c4de10.ff1831543e2e223a 192.168.13.219:6443 --discovery-token-ca-cert-hash sha256:f75e564824bb87a906a83f11fabc74b31c759a206dae75401448980e64d0953e

Где:

  • kubeadm join — Команда для добавления узлов к мастеру.
  • —token c4de10.ff1831543e2e223a — Токен для добавления.
  • 192.168.13.219:6443 — Хост и порт от мастер-ноды.
  • —discovery-token-ca-cert-hash sha256:f75e564824bb87a906a83f11fabc74b31c759a206dae75401448980e64d0953e — Дискавер токен.
  • —discovery-token-unsafe-skip-ca-verification — Можно использовать данную опцию для использывания обхода проверки токена обнаружения. Поскольку этот токен генерируется динамически, мы не могли включить его в действия. При создании ПРОД машин, укажите токен, предоставленный kubeadm init.

Получил ошибку:

CGROUPS_MEMORY: missing
	[WARNING FileExisting-crictl]: crictl not found in system path
[preflight] Some fatal errors occurred:
	[ERROR SystemVerification]: missing cgroups: memory
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`

Фиксим так, для начала — добавляем:

# echo "cgroup /sys/fs/cgroup cgroup defaults 0 0" >> /etc/fstab

Потом, открываем файл:

# vim /etc/default/grub

Находим строку «GRUB_CMDLINE_LINUX» и приводим к виду:

GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"

Потом, выполняем:

# update-grub && reboot

Немного о cgroups:

Установка cgroups в Unix/Linux

И потом, можно запускать (добавляем воркер к мастеру):

# kubeadm join --token 86669e.c66ab92be6dc5817 192.168.13.219:6443 --discovery-token-ca-cert-hash sha256:f8905cc439b0498eeb3a0de4bf7937640c96cb7063a2bc99f917433a994c4559

На kubernetes-master-1, запускаем:

# kubectl get nodes

Идем дальше — необходимо установить и добавить еще один воркер в созданный мастер!

Установка kubernetes-worker-2 на Debian 8

Аналогичные действия, проделываю и для kubernetes-worker-2. Но только с другим хостнеймом.

Установка kubernetes-worker-n на CenOS 7/Redhat 7

Можно добавлять другие воркеры по аналогии как я описывал ранее для kubernetes-master-1, но без инициализации мастера (что логично, не правдали?).

Деплой Kubernetes кластера в Unix/Linux

Приведу наглядный скриншот того, как выглядит развертывание первого приложения на Kubernetes:

Развертывание первого приложения на Kubernetes

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

Когда все ноды будут добавлены в кластер, должно получится что-то типа:

[root@kubernetes-master-1 ~]# kubectl get nodes
NAME                  STATUS       ROLES     AGE       VERSION
kubernetes-master-1   Ready        master    8m        v1.9.3
kubernetes-worker-1   Ready        <none>    54s       v1.9.3
kubernetes-worker-2   NotReady     <none>    40s       v1.9.3
[root@kubernetes-master-1 ~]#

Как видно что 2-й воркер не успел кодключится еще к кластеру. Через время подключится. Нужно пару минут подождать. Ну, пол работы сделано — осталось научится деплоить, мониторить и может чет еще упустил…

-=== СПОСОБ 1 ===-

Деплоим:

# kubectl create deployment nginx --image=nginx

Смотрим какие деплойменты имеются:

# kubectl get deployments
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     1         1         1            1           41s

Можно получить дополнительную инфу, выполнив:

# kubectl describe deployment nginx

Получаем что-то типа:

Name:                   nginx
Namespace:              default
CreationTimestamp:      Tue, 13 Mar 2018 14:18:29 +0200
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision=1
Selector:               app=nginx
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx
    Port:         <none>
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
OldReplicaSets:  <none>
NewReplicaSet:   nginx-7d7cbfc4f (1/1 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  2m    deployment-controller  Scaled up replica set nginx-7d7cbfc4f to 1

Делаем контейнер доступным в интернете:

# kubectl create service nodeport nginx --tcp=80:80

Смотрим статус:

# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        26m
nginx        NodePort    10.103.16.105   <none>        80:32564/TCP   23s

Проверяем работу контейнеров:

# curl kubernetes-worker-1:32564
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0A%20%20%20%20body%20%7B%0A%20%20%20%20%20%20%20%20width%3A%2035em%3B%0A%20%20%20%20%20%20%20%20margin%3A%200%20auto%3B%0A%20%20%20%20%20%20%20%20font-family%3A%20Tahoma%2C%20Verdana%2C%20Arial%2C%20sans-serif%3B%0A%20%20%20%20%7D%0A%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" />
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

На 2-м воркере:

# curl kubernetes-worker-2:32564

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0A%20%20%20%20body%20%7B%0A%20%20%20%20%20%20%20%20width%3A%2035em%3B%0A%20%20%20%20%20%20%20%20margin%3A%200%20auto%3B%0A%20%20%20%20%20%20%20%20font-family%3A%20Tahoma%2C%20Verdana%2C%20Arial%2C%20sans-serif%3B%0A%20%20%20%20%7D%0A%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" />
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

На мастере я не запускал воркер, по этому — смысла проверять, — нет.

Можно посмотреть сколько реплик имеется:

[root@kubernetes-master-1 ~]# kubectl get rs

NAME                             DESIRED   CURRENT   READY     AGE
kubernetes-bootcamp-69d869bf78   1         1         1         1d
nginx-7d7cbfc4f                  1         1         1         1d
[root@kubernetes-master-1 ~]#

Чтобы проверить поды, выполняем:

[root@kubernetes-master-1 ~]# kubectl get pods<br>
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-69d869bf78-84mvw   1/1       Running   0          1d
nginx-7d7cbfc4f-9s5dd                  1/1       Running   0          1d
[root@kubernetes-master-1 ~]#

Ролбэк Kubernetes кластера в Unix/Linux

Можно выполнять ролбэки:

# kubectl rollout status deployments nginx

Можно проверить хистори всех ролбеков:

[root@kubernetes-master-1 ~]# kubectl rollout history deployment/nginx<br>
deployments "nginx"
REVISION  CHANGE-CAUSE
1         <none>

[root@kubernetes-master-1 ~]#

Теперь я выполню откат к предыдущей версии:

# kubectl rollout undo deployment/nginx

Где:

  • —to-revision=2 — С данной опцией, можно задать до какой ревизии делаем откат.

Масштабирование Kubernetes кластера в Unix/Linux

Выполняем масштабирование:

# kubectl scale deployment nginx --replicas=5

deployment "nginx" scaled

Или:

# kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80

Проверяем:

# kubectl get deploy

NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1         1         1            1           1d
nginx                 5         5         5            5           1d
[root@kubernetes-master-1 ~]#

Можно выводить много полезной инфы вот так:

# kubectl get deployment,svc,pods,pvc

Все гениальное — просто. Но нужно время чтобы понять.

Мониторинг Kubernetes кластера в Unix/Linux

Дополню когда пойму как можно это сделать автоматически. У меня есть как минимум, 3 способа реализации. Но 1 из них — не очень хорошее решение.

  1. Можно заюзать zabbix и просетапать все kubernetes ноды, zabbix-агентами. Это реально будет работать, но как по мне — не ТРУЪ!
  2. Можно использовать consul для этого дела — это лучше решение чем заббикс.
  3. Так же, можно использовать  prometheus

Но об этом немного позже. Я дополню эту часть, обязательно!

Удаление Kubernetes кластера в Unix/Linux

Чтобы удалить ноду с кластера, на мастере, выполните:

# kubectl delete node your_node_for_delete

Если же нужно удалить вообще все — то обратное действие — установки.

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

# kubectl delete deployment nginx

Теоретически, данный кластер можно поднять минут за 10-15. Но я потратил больше времени, — выплывали всякие косяки. Вывод — данная цтилита, довольно прикольная и юзабельная, но как по мне — нужна доработка. Так же, хотелось отметить, что мой кластер работает, но его нужно оптимизировать/автоматизировать. Нужно больше времени чтобы понять как я могу это сделать.

Вот и все, статья «Установка Kubernetes кластера в Unix/Linux» завершена.

Работа с CloudFlare и Terraform в Unix/Linux

$
0
0

Работа с CloudFlare и Terraform в Unix/Linux

CloudFlare – это сервис по обслуживанию и обеспечению безопасности, который мы предоставляем своим клиентам. В среднем, сайт с CloudFlare загружается вдвое быстрее, потребляет на 60% меньше трафика, получает на 65% меньше нагрузки на сервер и при этом является более защищенным.

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Чтобы получить помощь по использованию команд, выполните:

$ terraform --help
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

Приступим к использованию!

Работа с CloudFlare и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkdir modules/cloudflare_record

Переходим в нее:

$ cd modules/cloudflare_record

Открываем файл:

$ vim cloudflare_record.tf

В данный файл, вставляем:

#---------------------------------------------------
# Add a record to the domain
#---------------------------------------------------
resource "cloudflare_record" "record" {
    count   = "${var.domain !="" && var.name !="" && var.value !="" ? 1 : 0}"

    domain      = "${var.domain}"
    name        = "${var.name}"
    value       = "${var.value}"
    type        = "${var.type}"
    ttl         = "${var.ttl}"
    priority    = "${var.priority}"
    proxied     = "${var.proxied}"
}

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
    description = " The name of the record"
    default     = "cloudflare_name"
}

variable "domain" {
    description = "The domain to add the record to"
    default     = ""
}

variable "value" {
    description = "The value of the record. Ex: 192.168.13.113"
    default     = ""
}

variable "type" {
    description = "The type of the record"
    default     = "A"
}

variable "ttl" {
    description = "The TTL of the record"
    default     = 3600
}

variable "priority" {
    description = "The priority of the record"
    default     = "1"
}

variable "proxied" {
    description = "Whether the record gets Cloudflare's origin protection."
    default     = ""
}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

И в него вставить нужно следующие строки:

output "record_ids" {
    description = ""
    value       = "${cloudflare_record.record.*.id}"
}

output "record_names" {
    description = ""
    value       = "${cloudflare_record.record.*.name}"
}

output "record_values" {
    description = ""
    value       = "${cloudflare_record.record.*.value}"
}

output "record_types" {
    description = ""
    value       = "${cloudflare_record.record.*.type}"
}

output "record_ttls" {
    description = ""
    value       = "${cloudflare_record.record.*.ttl}"
}

output "record_prioritys" {
    description = ""
    value       = "${cloudflare_record.record.*.priority}"
}

output "record_hostnames" {
    description = ""
    value       = "${cloudflare_record.record.*.hostname}"
}

output "record_proxieds" {
    description = ""
    value       = "${cloudflare_record.record.*.proxied}"
}

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir cloudflare_record && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "cloudflare" {
    email = ""
    token = ""
}
module "cloudflare_record" {
    source                          = "../../modules/cloudflare_record"
    name                            = "cloudflare_record"
}

В файле стоит прописать все необходимое, но самое главное:

  • email — Мыло при регистрации аккаунта в клаудфлюре.
  • token — Сгенерированный токен от клаудфлюра.

Еще полезности:

Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS VPC и Terraform в Unix/Linux

Работа с AWS S3 и Terraform в Unix/Linux

Работа с AWS EC2 и Terraform в Unix/Linux

Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux

Работа с AWS ELB и Terraform в Unix/Linux

Работа с AWS Route53 и Terraform в Unix/Linux

Работа с AWS RDS и Terraform в Unix/Linux

Работа с AWS SNS и Terraform в Unix/Linux

Работа с AWS SQS и Terraform в Unix/Linux

Работа с AWS KMS и Terraform в Unix/Linux

Работа с AWS NLB и Terraform в Unix/Linux

Работа с AWS CloudWatch и Terraform в Unix/Linux

Работа с AWS ALB и Terraform в Unix/Linux

Работа с AWS MQ broker и Terraform в Unix/Linux

Работа с AWS EFS и Terraform в Unix/Linux

Работа с AWS elasticache и Terraform в Unix/Linux

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Проверим валидацию:

$ terraform validate

Запускем прогон:

$ terraform plan

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Весь материал аплоаджу в github аккаунт для удобства использования:

$ git clone https://github.com/SebastianUA/terraform.git

Вот и все на этом. Данная статья «Работа с CloudFlare и Terraform в Unix/Linux» завершена.

Установка flock в Unix/Linux

$
0
0

Установка flock в Unix/Linux

flock — утилита, которая позволяет использовать лок-файл для предотвращения запуска копии процесса (вашего скрипта, крона или чего-то еще). Например, используя cron нужно быть уверенным, что предыдущий запуск вашего скрипта уже завершен.

Установка flock в Unix/Linux

У Linux ОС, данная утилита уже идит с самой коробки.

Установка flock в Mac OS X

Для начала, устанавливаем HOMEBREW, после чего — выполняем:

$ brew tap discoteq/discoteq

Этой командой, что-то поставится в ОС, осталось выполнить установку flock-а:

$ brew install flock

Можно использовать!

Установка flock на другие Unix/Linux ОС

Если в системе не имеется этой утилиты, то можно собрать ее из сорцов:

# FLOCK_VERSION=0.2.3 \
wget https://github.com/discoteq/flock/releases/download/v${FLOCK_VERSION}/flock-${FLOCK_VERSION}.tar.xz \
xz -dc flock-${FLOCK_VERSION}.tar.xz | tar -x \
cd flock-${FLOCK_VERSION} \
./configure \
make \
make install

Вот и все!

Использование flock в Unix/Linux

Например, можно использовать:

$ `which flock` -w 600 /var/tmp/test_script.lock ./test_script.sh

Или:

$ `which flock` -w600 /var/tmp/myscript.lock bash myscript.sh

Данная команда, запустит ./test_script.sh скрипт (он находится в текущей директории). Так же, будет создан test_script.lock файл. Пока он активен, новый вызов скрипта не будет выполнен из-за лока. Когда программа (скрипт) завершится, то лок файл будет удален, тем самым — можно будет использовать повторый запуск. Параметр -w 600 определяет время ожидания комманды flock на освобождение lock-файла. Чтобы убрать время блокировки лока, используйте «-w 0» опцию.  Так же, можно ожидать бесконечно долгое временя, — тогда нужно параметр опустить.

Таким вот способом, можно предотвратить повторный запуск ващих скриптов. Вот и все, статья «Установка flock в Unix/Linux» завершена.

Viewing all 152 articles
Browse latest View live