OpenStack Heat AutoScale Juno

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску

OpenStack Heat AutoScaling (Juno)

Это короткая заметка про использование автоскейлинша с хитом и цейлометром в Juno (сборка Mirantis и в ванильном джуно может не хватать каких-то бекпортов, я это специально не проверял)

Введение

Дальше по тексту я буду приводить только части шаблонов, полные шаблоны - в конце, отдельным разделом. Это нужно для простоты - читать "простыню" не удобно.
Основная задача формулируется так:

  • Есть абстрактное приложение которое надо масштабировать от нагрузки
  • При превышении порога по какой-либо метрике добавлять +N экземпляров приложения (виртуальную машину)
  • При отсутствии нагрузки удалять -M экземпляров приложения (виртуальных машин)
  • M и N - целые числа (в моем примере они будут равны 1)

Создание стека

Команду создания стека я вынес в отдельный скрипт для простоты

D=` date  +%Y%m%d%H%M%S`

heat stack-create ABC-${D} -f asglb.yaml  \
-P "key_name=demo;net=net04;subnet=net04__subnet;public_net=net04_ext;app_lb_port=80;timeout=600;min_asg_size=1;max_asg_size=3;launch_asg_size=3"

2

3

4

asglb.yaml

heat_template_version: 2014-10-16

description: |

 Template which tests Neutron load balancing requests to members of
 Heat AutoScalingGroup.
 Instances must be running some webserver on a given app_port
 producing HTTP response that is different between servers
 but stable over time for given server.
 Auto-scaling is driven by Ceilometer alarms.
 Both HTTP and SSH access are load-balanced.

parameters:

 flavor:
   type: string
   default: m1.compact
 image:
   type: string
   default: Centos 6.5 x64 (pre installed node.js stack)
 username:
   type: string
   default: root
 key_name:
   type: string
   default: ericsson
 net:
   type: string
   default: net04
 subnet:
   type: string
   default: net04__subnet
 public_net:
   type: string
   default: net04_ext
 app_port:
   type: number
   default: 1026
 app_lb_port:
   type: number
   default: 80
 timeout:
   type: number
   default: 600
 min_asg_size:
   type: number
   default: 1
 max_asg_size:
   type: number
   default: 3
 launch_asg_size:
   type: number
   default: 2
 cooldown:
   type: number
   default: 60

resources:

 app_sec_group:
   type: OS::Neutron::SecurityGroup
   properties:
     rules:
     - remote_ip_prefix: 0.0.0.0/0
       protocol: tcp
       port_range_min: { get_param: app_port }
       port_range_max: { get_param: app_port }
 ssh_sec_group:
   type: OS::Neutron::SecurityGroup
   properties:
     rules:
     - remote_ip_prefix: 0.0.0.0/0
       protocol: tcp
       port_range_min: 22
       port_range_max: 22
 asg:
   type: OS::Heat::AutoScalingGroup
   properties:
     desired_capacity: { get_param: launch_asg_size }
     max_size: { get_param: max_asg_size }
     min_size: { get_param: min_asg_size }
     cooldown: { get_param: cooldown }
     resource:
  1. type: https://raw.githubusercontent.com/olguncengiz/hot/master/app_server_neutron.yaml
       type: app_server_neutron.yaml
       properties:
         mdata: {"metering.stack": {get_param: "OS::stack_id"}}
         image: { get_param: image }
         flavor: { get_param: flavor }
         key_name: { get_param: key_name }
         net: { get_param: net}
         app_sec_group: { get_resource: app_sec_group }
         ssh_sec_group: { get_resource: ssh_sec_group }
         app_port: { get_param: app_port }
         app_pool_id: { get_resource: app_pool }
         ssh_pool_id: { get_resource: ssh_pool }
         timeout: { get_param: timeout }
 scale_up:
   type: OS::Heat::ScalingPolicy
   properties:
     adjustment_type: change_in_capacity
     auto_scaling_group_id: { get_resource: asg }
     scaling_adjustment: 1
 scale_down:
   type: OS::Heat::ScalingPolicy
   properties:
     adjustment_type: change_in_capacity
     auto_scaling_group_id: { get_resource: asg }
     scaling_adjustment: -1
 cpu_alarm_high:
   type: OS::Ceilometer::Alarm
   properties:
     description: Scale-up if the average CPU > 50% for 1 minute
     meter_name: cpu_util
     statistic: avg
     period: 60
     evaluation_periods: 1
     threshold: 50
     alarm_actions:
       - {get_attr: [scale_up, alarm_url]}
     matching_metadata: {"metadata.user_metadata.stack": {get_param: "OS::stack_id"}}
     comparison_operator: gt
     repeat_actions: true
 cpu_alarm_low:
   type: OS::Ceilometer::Alarm
   properties:
     description: Scale-down if the average CPU < 15% for 1 minute
     meter_name: cpu_util
     statistic: avg
     period: 60
     evaluation_periods: 1
     threshold: 15
     alarm_actions:
       - {get_attr: [scale_down, alarm_url]}
     matching_metadata: {"metadata.user_metadata.stack": {get_param: "OS::stack_id"}}
     comparison_operator: lt
     repeat_actions: true
 app_health_monitor:
   type: OS::Neutron::HealthMonitor
   properties:
     delay: 3
     type: HTTP
     timeout: 3
     max_retries: 3
 app_pool:
   type: OS::Neutron::Pool
   properties:
     lb_method: ROUND_ROBIN
     protocol: HTTP
     subnet: { get_param: subnet }
     monitors:
     - { get_resource: app_health_monitor }
     vip:
       protocol_port: { get_param: app_lb_port }
 app_floating_ip:
    type: OS::Neutron::FloatingIP
    properties:
      floating_network: { get_param: public_net }
      port_id:
        { get_attr: [app_pool, vip, 'port_id'] }
 ssh_pool:
   type: OS::Neutron::Pool
   properties:
     lb_method: ROUND_ROBIN
     protocol: TCP
     subnet: { get_param: subnet }
     vip:
       protocol_port: 22
 ssh_floating_ip:
    type: OS::Neutron::FloatingIP
    properties:
      floating_network: { get_param: public_net }
      port_id:
        { get_attr: [ssh_pool, vip, 'port_id'] }

outputs:

 app_lb_url:
   description: URL of the loadbalanced app
   value:
     str_replace:
       template: http://IP_ADDRESS:PORT
       params:
         IP_ADDRESS: { get_attr: [ app_floating_ip, floating_ip_address ] }
         PORT: { get_param: app_lb_port }
 ssh_lb_url:
   description: command for the loadbalanced SSH access
   value:
     str_replace:
       template: ssh -i KEY.pem USER@IP_ADDRESS
       params:
         IP_ADDRESS: { get_attr: [ ssh_floating_ip, floating_ip_address ] }
         KEY: { get_param: key_name }
         USER: { get_param: username }
 scale_up_hook:
   description: POST to this URL for manual scale up
   value: {get_attr: [scale_up, alarm_url]}
 scale_down_hook:
   description: POST to this URL for manual scale up
   value: {get_attr: [scale_down, alarm_url]}

APP_server_neutron.yaml

HeatTemplateFormatVersion: 2012-12-12

Description: |
  App server that is a member of Neutron Pool.

Parameters:
  mdata:
    Type: Json
  image:
    Type: String
  flavor:
    Type: String
  key_name:
    Type: String
  net:
    Type: String
  app_sec_group:
    Type: String
  ssh_sec_group:
    Type: String
  app_pool_id:
    Type: String
  ssh_pool_id:
    Type: String
  app_port:
    Type: Number
    Default: 1026
  timeout:
    Type: Number
#  mem_alarm_low:
#    Type: String
#  mem_alarm_high:
#    Type: String
  secret_key:
    Type: String
  access_key:
    Type: String
  stack_id:
    Type: String

Resources:

  server:
    Type: OS::Nova::Server
    Properties:
      metadata: { Ref: mdata }
      image: { Ref: image }
      flavor: { Ref: flavor }
      key_name: { Ref: key_name }
      networks:
        - network: { Ref: net }
      security_groups:
        - { Ref: app_sec_group }
        - { Ref: ssh_sec_group }
      user_data:
        "Fn::Base64": {
        "Fn::Join" : ["",
        [
        "#!/bin/bash -v\n",
        "\n",
        "#yum -y install heat-cfntools-1.2.6-4.el6.noarch\n",
        "#/usr/bin/cfn-create-aws-symlinks\n",
        "\n",
        "mkdir  -p   \"/etc/cfn/\"\n ",
        "touch /etc/cfn/cfn-credentials\n",
        "echo   \"AWSAccessKeyId=\"",  { "Ref" : "access_key" } , ">>/etc/cfn/cfn-credentials\n",
        "echo   \"AWSSecretKey=\"", {"Ref" : "secret_key" }, ">> /etc/cfn/cfn-credentials\n" ,
        "\n",
        "service crond restart \n",
        "yum -y install cpulimit stress screen \n",
        "cd /tmp ; git clone https://github.com/julman99/eatmemory.git; cd eatmemory; make;  make install \n",
        "pip install python-ceilometerclient \n",
        "echo \"export LC_ALL=C\" >> /root/openrc \n",
        "echo \"export OS_NO_CACHE='true'\" >> /root/openrc \n",
        "echo \"export OS_TENANT_NAME='admin'\" >> /root/openrc \n",
        "echo \"export OS_USERNAME='admin'\" >> /root/openrc \n",
        "echo \"export OS_PASSWORD='admin'\" >> /root/openrc \n",
        "echo \"export OS_AUTH_URL='http://159.8.10.162:5000/v2.0/'\" >> /root/openrc \n",
        "echo \"export OS_AUTH_STRATEGY='keystone'\" >> /root/openrc \n",
        "echo \"export OS_REGION_NAME='RegionOne'\" >> /root/openrc \n",
        "echo \"export CINDER_ENDPOINT_TYPE='publicURL'\" >> /root/openrc \n",
        "echo \"export GLANCE_ENDPOINT_TYPE='publicURL'\" >> /root/openrc \n",
        "echo \"export KEYSTONE_ENDPOINT_TYPE='publicURL'\" >> /root/openrc \n",
        "echo \"export NOVA_ENDPOINT_TYPE='publicURL'\" >> /root/openrc \n",
        "echo \"export NEUTRON_ENDPOINT_TYPE='publicURL'\" >> /root/openrc \n",
        "ceilometer sample-create -r 6c3fd865-a478-4afc-909e-eced382de432  -m test_meter --meter-type gauge  --meter-unit percents --sample-volume 99 --resource-metadata '{\"metering.metadata.user_metadata.stack\": \"", { "Ref": "stack_id" }, "\"}'\n",
        { "Fn::GetAtt": ["handle", "curl_cli" ] }, " --data-binary '{\"status\": \"SUCCESS\"}'\n"
         ] ]
        }


  handle:
    Type: OS::Heat::WaitConditionHandle

  waiter:
    Type: OS::Heat::WaitCondition
    DependsOn: server
    Properties:
      timeout: { Ref: timeout }
      handle: { Ref: handle }

  app_pool_member:
    Type: OS::Neutron::PoolMember
    DependsOn: waiter
    Properties:
      address: { "Fn::GetAtt": [ server, first_address ] }
      pool_id: { Ref: app_pool_id }
      protocol_port: { Ref: app_port }

  ssh_pool_member:
    Type: OS::Neutron::PoolMember
    DependsOn: waiter
    Properties:
      address: { "Fn::GetAtt": [ server, first_address ] }
      pool_id: { Ref: ssh_pool_id }
      protocol_port: 22

Outputs:
  WaitNotify:
    Value: { "Fn::GetAtt": ["handle", "curl_cli" ]  }