I create Heat Template with Powershell commands and my template is not getting executed after adding deployment section. I have added this section to get output for commands.Below shown template I am using :
heat_template_version: 2016-10-14
description: Template to install HyperV Feature in Server
resources:
floating_ip:
type: OS::Neutron::FloatingIP
properties:
floating_network: Net_External_16
instance:
type: OS::Nova::Server
properties:
name: machine2
flavor: LARGE
networks:
- network: 71xxxx85-8a24-475b-9xxc-169xxxxxbb0
security_groups:
- default
- all_open
block_device_mapping_v2:
- device_name: /dev/vpa
volume_id: {get_resource: volume}
delete_on_termination: "true"
volume:
type: OS::Cinder::Volume
properties:
size: 25
image: 51xxxxxbe-44e6-4206-920c-xxxxxxxxxx
name: {get_param: volumename}
ps_script:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config:
str_replace:
template: |
#ps1_sysnative
$log = New-Item "C:\check_file.txt" -Type File
start-sleep -s 20
install-windowsfeature -Name DNS -IncludeManagementTools
start-sleep -s 60
$pass = "_parameter_1_"
Add-content $log $pass
params:
_parameter_1_: {get_param: parameter1}
association:
type: OS::Neutron::FloatingIPAssociation
properties:
floatingip_id: {get_resource: floating_ip}
port_id: {get_attr: [instance, addresses, 71xxxxx85-8a24-4xxb-9xxc-16xxxx84bb0, 0, port]}
deployment:
type: OS::Heat::SoftwareDeployment
properties:
config: {get_resource: ps_script}
server: {get_resource: instance }
outputs:
instance_ip:
description: Ipaddress
value: {get_attr: [instance,addresses]}
result:
description: Checkoutput
value: {get_attr: [deployent]}
If anybody tried this same method or any other solution they can provide to get output for powershell commands executed from Template.
Add the line user_data_format: SOFTWARE_CONFIG under OS::Nova::Server properties :
instance:
type: OS::Nova::Server
properties:
name: machine2
flavor: LARGE
networks:
- network: 71xxxx85-8a24-475b-9xxc-169xxxxxbb0
security_groups:
- default
- all_open
block_device_mapping_v2:
- device_name: /dev/vpa
volume_id: {get_resource: volume}
delete_on_termination: "true"
user_data_format: SOFTWARE_CONFIG
This line is required when there is another resource for software configuration.
And also there is a typo in the output section deployent -> deployment
outputs:
instance_ip:
description: Ipaddress
value: { get_attr: [instance,addresses] }
result:
description: Checkoutput
value: { get_attr: [deployment] }
Note: Add the space after { and before }. For example :
{ get_resource: volume }
Related
I would like to define some "global resources" (such as security groups) and then be able to export them to the templates in charge of the deployment nodes.
I tried following this documentation page: https://docs.openstack.org/heat/yoga/template_guide/composition.html
sec-group.yaml:
heat_template_version: 2018-08-31
resources:
sec_group:
type: OS::Neutron::SecurityGroup
properties:
name: my-sec-group
description: my security group
rules:
- direction: egress
ethertype: IPv4
- direction: egress
ethertype: IPv6
(simplified) deploy-node.yaml
...
...
resources:
flavor:
type: OS::Nova::Flavor
properties:
ram: 4096
disk: 20
vcpus: 1
instance:
type: OS::Nova::Server
properties:
flavor: { get_resource: flavor }
image: { get_param: image }
key_name: { get_param: key_name }
metadata: { get_param: metadata }
name: { get_param: "OS::stack_name" }
networks:
- port: { get_resource: instance_port }
sec_group:
type: sec-group.yaml
instance_port:
type: OS::Neutron::Port
properties:
network: { get_param: instance_net }
fixed_ips:
- subnet_id: { get_param: instance_subnet }
security_groups:
- { get_resource: sec_group }
However, Openstack returns EntityNotFound for the security group when creating the instance_port resource. What am I doing wrong?
I am trying to launch a Drupal container using ecs and connecting to a RDS MySQL instance for the database, using CloudFormation Templates in nested form.The nginx image is working fine but I am not so sure about drupal. The Instances works perfectly until the install part. But after which it provides this output.
Could really use some help.
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Description: Name of an existing EC2 KeyPair to enable SSH access to the ECS instances.
VpcId:
Type: AWS::EC2::VPC::Id
Description: Select a VPC that allows instances access to the Internet.
SubnetId:
Type: List<AWS::EC2::Subnet::Id>
Description: Select at two subnets in your selected VPC.
DesiredCapacity:
Type: Number
Default: '1'
Description: Number of instances to launch in your ECS cluster.
MaxSize:
Type: Number
Default: '1'
Description: Maximum number of instances that can be launched in your ECS cluster.
InstanceType:
Description: EC2 instance type
Type: String
Default: t2.medium
AllowedValues:
- t2.micro
- t2.small
- t2.medium
- t2.large
- m3.medium
- m3.large
- m3.xlarge
- m3.2xlarge
- m4.large
- m4.xlarge
- m4.2xlarge
- m4.4xlarge
- m4.10xlarge
- c4.large
- c4.xlarge
- c4.2xlarge
- c4.4xlarge
- c4.8xlarge
- c3.large
- c3.xlarge
- c3.2xlarge
- c3.4xlarge
- c3.8xlarge
- r3.large
- r3.xlarge
- r3.2xlarge
- r3.4xlarge
- r3.8xlarge
- i2.xlarge
- i2.2xlarge
- i2.4xlarge
- i2.8xlarge
ConstraintDescription: Please choose a valid instance type.
DBInstanceID:
Default: mydbinstance
Description: My database instance
Type: String
MinLength: '1'
MaxLength: '63'
AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
ConstraintDescription: >-
Must begin with a letter and must not end with a hyphen or contain two
consecutive hyphens.
DBName:
Default: mydb
Description: My database
Type: String
MinLength: '1'
MaxLength: '64'
AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
ConstraintDescription: Must begin with a letter and contain only alphanumeric characters.
DBInstanceClass:
Default: db.m5.large
Description: DB instance class
Type: String
ConstraintDescription: Must select a valid DB instance type.
DBAllocatedStorage:
Default: '50'
Description: The size of the database (GiB)
Type: Number
MinValue: '5'
MaxValue: '1024'
ConstraintDescription: must be between 20 and 65536 GiB.
DBUsername:
NoEcho: 'true'
Description: Username for MySQL database access
Type: String
MinLength: '1'
MaxLength: '16'
AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
DBPassword:
NoEcho: 'true'
Description: Password MySQL database access
Type: String
MinLength: '8'
MaxLength: '41'
AllowedPattern: '[a-zA-Z0-9]*'
ConstraintDescription: must contain only alphanumeric characters.
Mappings:
AWSRegionToAMI:
us-east-1:
AMIID: ami-09bee01cc997a78a6
us-east-2:
AMIID: ami-0a9e12068cb98a01d
us-west-1:
AMIID: ami-0fa6c8d131a220017
us-west-2:
AMIID: ami-078c97cf1cefd1b38
eu-west-1:
AMIID: ami-0c9ef930279337028
eu-central-1:
AMIID: ami-065c1e34da68f2b02
ap-northeast-1:
AMIID: ami-02265963d1614d04d
ap-southeast-1:
AMIID: ami-0b68661b29b9e058c
ap-southeast-2:
AMIID: ami-00e4b147599c13588
ap-south-1:
AMIID: ami-036eaa870decb368d
Resources:
cloudfrontdistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
#DefaultRootObject:
#CacheBehaviors:
#- ViewerProtocolPolicy: allow-all
#TargetOrginId: vn2699
#PathPattern: /*.php
#LambdaFunctionAssociations:
# - EventType: string-value
# LambdaFunctionARN: string-value
Enabled: True
DefaultCacheBehavior:
TargetOriginId: vn2699
CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad
ViewerProtocolPolicy: allow-all
#LambdaFunctionAssociations:
# - EventType: string-value
# LambdaFunctionARN: string-value
IPV6Enabled: False
Origins:
- DomainName: !GetAtt ECSALB.DNSName
Id: vn2699
CustomOriginConfig:
HTTPPort: 80
OriginKeepaliveTimeout: 5
OriginProtocolPolicy: http-only
OriginReadTimeout: 30
Tags:
- Key: Name
Value: ECS-example
ReactS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: reacts3vn2699
WebsiteConfiguration:
IndexDocument: index.html
S3accessPoint:
Type: AWS::S3::AccessPoint
Properties:
Bucket: !Ref 'ReactS3Bucket'
Name: reactaccesspointvn2699
VpcConfiguration:
VpcId: !Ref 'VpcId'
ECSCluster:
Type: AWS::ECS::Cluster
#DependsOn: ECSAutoScalingGroup
#Properties:
#CapacityProviders:
#- Nse
ECSCapacityProvider:
Type: AWS::ECS::CapacityProvider
Properties:
AutoScalingGroupProvider:
AutoScalingGroupArn: !Ref ECSAutoScalingGroup
Name: Nse
DBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: DB Security Group
VpcId: !Ref 'VpcId'
SecurityGroupIngress:
- FromPort: 3306
IpProtocol: tcp
ToPort: 3306
SourceSecurityGroupId: !GetAtt EcsSecurityGroup.GroupId
- FromPort: 3306
IpProtocol: tcp
ToPort: 3306
SourceSecurityGroupId: !GetAtt BastionSecurityGroup.GroupId
BastionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: BastionHost security group
VpcId: !Ref 'VpcId'
SecurityGroupIngress:
- FromPort: 22
IpProtocol: tcp
ToPort: 22
CidrIp: 0.0.0.0/0
- FromPort: 3306
IpProtocol: tcp
ToPort: 3306
#SourceSecurityGroupId: !GetAtt DBSecurityGroup.GroupId
CidrIp: 0.0.0.0/0
EcsSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: ECS Security Group
VpcId: !Ref 'VpcId'
EcsSecurityGroupHTTPinbound:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref 'EcsSecurityGroup'
IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: 0.0.0.0/0
EcsSecurityGroupSQLInbound:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref 'EcsSecurityGroup'
IpProtocol: tcp
FromPort: '3306'
ToPort: '3306'
SourceSecurityGroupId: !GetAtt DBSecurityGroup.GroupId
EcsSecurityGroupSSHinbound:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref 'EcsSecurityGroup'
IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: 0.0.0.0/0
NestedStackDB:
Type: AWS::CloudFormation::Stack
DependsOn:
- EcsSecurityGroup
- DBSecurityGroup
- BastionSecurityGroup
Properties:
TemplateURL: bucket-link
Parameters:
SecurityGroupBastion: !GetAtt BastionSecurityGroup.GroupId
SecurityGroup: !GetAtt DBSecurityGroup.GroupId
DBInstanceID: !Ref DBInstanceID
DBName: !Ref DBName
DBInstanceClass: !Ref DBInstanceClass
DBUsername: !Ref DBUsername
DBPassword: !Ref DBPassword
DBAllocatedStorage: !Ref DBAllocatedStorage
KeyName: !Ref KeyName
EcsSecurityGroupALBports:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref 'EcsSecurityGroup'
IpProtocol: tcp
FromPort: '31000'
ToPort: '61000'
SourceSecurityGroupId: !Ref 'EcsSecurityGroup'
EcsSecurityGroupDrupal:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref 'EcsSecurityGroup'
IpProtocol: tcp
FromPort: '9000'
ToPort: '9000'
SourceSecurityGroupId: !Ref 'EcsSecurityGroup'
CloudwatchLogsGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Join ['-', [ECSLogGroup, !Ref 'AWS::StackName']]
RetentionInDays: 14
taskdefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Join ['', [!Ref 'AWS::StackName', -ecs-demo-app]]
ExecutionRoleArn: arn:aws:iam::<accNo>:role/ecsTaskExecutionRole
#TaskRoleArn: arn:aws:iam::aws:policy/AmazonS3FullAccess
NetworkMode: bridge
#RequiredCompatibilities:
#- "EC2"
ContainerDefinitions:
- Name: webserver
Cpu: 256
DependsOn:
- Condition: "START"
ContainerName: "drupal"
#Essential: 'true'
Image: nginx-drupal:latest
Memory: 512
Hostname: webserver
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: ecs-demo-app
VolumesFrom:
- SourceContainer: drupal
PortMappings:
- ContainerPort: 80
HostPort: 80
- Name: drupal
Cpu: 256
Essential: false
Image: drupal:9.1.5-php8.0-fpm-alpine3.12
Memory: 512
Hostname: drupal
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: ecs-demo-app
MountPoints:
- ContainerPath: /var/www/html
SourceVolume: drupal-data
PortMappings:
- ContainerPort: 9000
Volumes:
- Name: drupal-data
ECSALB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
#DependsOn: service
Properties:
Name: ECSALB
Scheme: internet-facing
LoadBalancerAttributes:
- Key: idle_timeout.timeout_seconds
Value: '30'
Subnets: !Ref 'SubnetId'
SecurityGroups: [!Ref 'EcsSecurityGroup']
ALBListener:
Type: AWS::ElasticLoadBalancingV2::Listener
DependsOn: ECSServiceRole
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'ECSTG'
#RedirectConfig:
#Protocol: "HTTP"
#Host: "#{host}"
#Path: "/#{path}"
#Query: "#{query}"
#Port: 80
#StatusCode: "HTTP_302"
LoadBalancerArn: !Ref 'ECSALB'
Port: '80'
Protocol: HTTP
ECSALBListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
DependsOn: ALBListener
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref 'ECSTG'
#RedirectConfig:
#Protocol: "HTTP"
#Host: "#{host}"
#Path: "/#{path}"
#Query: "#{query}"
#Port: 80
#StatusCode: "HTTP_302"
Conditions:
- Field: path-pattern
Values: [/]
ListenerArn: !Ref 'ALBListener'
Priority: 1
ECSTG:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
DependsOn: ECSALB
Properties:
HealthCheckIntervalSeconds: 80
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 60
HealthyThresholdCount: 2
Matcher:
HttpCode: 302
Name: ECSTG
Port: 80
Protocol: HTTP
TargetType: instance
UnhealthyThresholdCount: 2
VpcId: !Ref 'VpcId'
ECSAutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
#VPCZoneIdentifier: !Ref 'SubnetId'
VPCZoneIdentifier:
- subnet-0c228c2e5e42708aa
- subnet-0bf3fcea01d2dd0a4
- subnet-0c6a01197480771b3
LaunchConfigurationName: !Ref 'ContainerInstances'
#LoadBalancerNames:
#- ECSALB
TargetGroupARNs: [!Ref 'ECSTG']
MinSize: '1'
MaxSize: !Ref 'MaxSize'
DesiredCapacity: !Ref 'DesiredCapacity'
CreationPolicy:
ResourceSignal:
Timeout: PT15M
UpdatePolicy:
AutoScalingReplacingUpdate:
WillReplace: 'true'
ContainerInstances:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: !FindInMap [AWSRegionToAMI, !Ref 'AWS::Region', AMIID]
SecurityGroups: [!Ref 'EcsSecurityGroup']
InstanceType: !Ref 'InstanceType'
IamInstanceProfile: !Ref 'EC2InstanceProfile'
KeyName: !Ref 'KeyName'
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
yum update -y
yum install -y aws-cfn-bootstrap
#/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}
#sudo cat /var/log/cloud-init-output.log
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}
service:
Type: AWS::ECS::Service
DependsOn:
- ALBListener
#- ECSAutoScalingGroup
Properties:
Cluster: !Ref 'ECSCluster'
DesiredCount: '1'
HealthCheckGracePeriodSeconds: 2147483647
LoadBalancers:
- ContainerName: webserver
ContainerPort: '80'
TargetGroupArn: !Ref 'ECSTG'
#LoadBalancerName: !GetAtt ECSALB.LoadBalancerName
#LoadBalancerName: ECSALB
#NetworkConfiguration:
# AwsvpcConfiguration:
# AssignPublicIp: ENABLED
# SecurityGroups:
# - !Ref 'EcsSecurityGroup'
# Subnets: !Ref 'SubnetId'
#ServiceName: Ecs
Role: !Ref 'ECSServiceRole'
TaskDefinition: !Ref 'taskdefinition'
ECSServiceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: ecs-service
PolicyDocument:
Statement:
- Effect: Allow
Action: ['elasticloadbalancing:DeregisterInstancesFromLoadBalancer', 'elasticloadbalancing:DeregisterTargets',
'elasticloadbalancing:Describe*', 'elasticloadbalancing:RegisterInstancesWithLoadBalancer',
'elasticloadbalancing:RegisterTargets', 'ec2:Describe*', 'ec2:AuthorizeSecurityGroupIngress']
Resource: '*'
ServiceScalingTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
#DependsOn: service
Properties:
MaxCapacity: 3
MinCapacity: 1
ResourceId: !Join ['', [service/, !Ref 'ECSCluster', /, !GetAtt [service, Name]]]
RoleARN: !GetAtt [AutoscalingRole, Arn]
ScalableDimension: ecs:service:DesiredCount
ServiceNamespace: ecs
ServiceScalingPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: AStepPolicy
PolicyType: StepScaling
ScalingTargetId: !Ref 'ServiceScalingTarget'
StepScalingPolicyConfiguration:
AdjustmentType: PercentChangeInCapacity
Cooldown: 60
MetricAggregationType: Average
StepAdjustments:
- MetricIntervalLowerBound: 0
ScalingAdjustment: 200
ALB500sAlarmScaleUp:
Type: AWS::CloudWatch::Alarm
Properties:
EvaluationPeriods: '1'
Statistic: Average
Threshold: '10'
AlarmDescription: Alarm if our ALB generates too many HTTP 500s.
Period: '60'
AlarmActions: [!Ref 'ServiceScalingPolicy']
Namespace: AWS/ApplicationELB
Dimensions:
- Name: LoadBalancer
Value: !GetAtt
- ECSALB
- LoadBalancerFullName
ComparisonOperator: GreaterThanThreshold
MetricName: HTTPCode_ELB_5XX_Count
EC2Role:
Type: AWS::IAM::Role
Properties:
#ManagedPolicyArns:
#- arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ec2.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: ecs-service
PolicyDocument:
Statement:
- Effect: Allow
Action: ['ecs:CreateCluster', 'ecs:DeregisterContainerInstance', 'ecs:DiscoverPollEndpoint',
'ecs:Poll', 'ecs:RegisterContainerInstance', 'ecs:StartTelemetrySession',
'ecs:Submit*', 'logs:CreateLogStream', 'logs:PutLogEvents']
Resource: '*'
AutoscalingRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [application-autoscaling.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: service-autoscaling
PolicyDocument:
Statement:
- Effect: Allow
Action: ['application-autoscaling:*', 'cloudwatch:DescribeAlarms', 'cloudwatch:PutMetricAlarm',
'ecs:DescribeServices', 'ecs:UpdateService']
Resource: '*'
EC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles: [!Ref 'EC2Role']
Outputs:
ecsservice:
Value: !Ref 'service'
ecscluster:
Value: !Ref 'ECSCluster'
ECSALB:
Description: Your ALB DNS URL
Value: !Join ['', [!GetAtt [ECSALB, DNSName]]]
taskdef:
Value: !Ref 'taskdefinition'
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
KeyName:
Type: AWS::EC2::KeyPair::KeyName
SecurityGroupBastion:
Type: AWS::EC2::SecurityGroup::Id
SecurityGroup:
Type: AWS::EC2::SecurityGroup::Id
DBInstanceID:
Default: mydbinstance
Description: My database instance
Type: String
MinLength: '1'
MaxLength: '63'
AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
ConstraintDescription: >-
Must begin with a letter and must not end with a hyphen or contain two
consecutive hyphens.
DBName:
Default: mydb
Description: My database
Type: String
MinLength: '1'
MaxLength: '64'
AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
ConstraintDescription: Must begin with a letter and contain only alphanumeric characters.
DBInstanceClass:
Default: db.m5.large
Description: DB instance class
Type: String
ConstraintDescription: Must select a valid DB instance type.
DBAllocatedStorage:
Default: '50'
Description: The size of the database (GiB)
Type: Number
MinValue: '5'
MaxValue: '1024'
ConstraintDescription: must be between 20 and 65536 GiB.
DBUsername:
NoEcho: 'true'
Description: Username for MySQL database access
Type: String
MinLength: '1'
MaxLength: '16'
AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
DBPassword:
NoEcho: 'true'
Description: Password MySQL database access
Type: String
MinLength: '8'
MaxLength: '41'
AllowedPattern: '[a-zA-Z0-9]*'
ConstraintDescription: must contain only alphanumeric characters.
Resources:
DrupalDB:
Type: 'AWS::RDS::DBInstance'
Properties:
DBInstanceIdentifier: !Ref DBInstanceID
DBName: !Ref DBName
DBInstanceClass: !Ref DBInstanceClass
AllocatedStorage: !Ref DBAllocatedStorage
Engine: MySQL
EngineVersion: 8.0.20
MasterUsername: !Ref DBUsername
MasterUserPassword: !Ref DBPassword
DBSubnetGroupName: !Ref DBSubnetGroupDrupal
#MonitoringInterval: '60'
#MonitoringRoleArn: ''
AllowMajorVersionUpgrade: true
#AssociatedRoles:
BackupRetentionPeriod: 1
#CopyTagsToSnapshot:
#DBClusterIdentifier:
#DBSecurityGroups:
#KmsKeyId:
MultiAZ: true
Port: 3306
#SourceDBInstanceIdentifier:
#PubliclyAccessible:
#SourceRegion:
StorageType: standard
VPCSecurityGroups: [!Ref SecurityGroup]
DBSubnetGroupDrupal:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: 'For Drupal DB'
DBSubnetGroupName: 'DrupalDB'
SubnetIds:
- subnet-01cc7a208ce068cd7
- subnet-0ed0f1627396e1a96
- subnet-0b38eb422f032ea76
BastionHost:
Type: AWS::EC2::Instance
Properties:
AvailabilityZone: ap-south-1a
#BlockDeviceMappings:
ImageId: ami-068d43a544160b7ef
InstanceType: t2.micro
KeyName: !Ref KeyName
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: 0
GroupSet:
- !Ref SecurityGroupBastion
SubnetId: subnet-0c228c2e5e42708aa
I'm using cloudify community version 19.01.24.
Trying to figure out how to auto-scale a group of two VMs. Here's what I came up with so far (skipped irrelevant parts):
monitored_vm1_port:
type: cloudify.openstack.nodes.Port
properties:
openstack_config: *openstack_config
relationships:
- type: cloudify.relationships.contained_in
target: proxy_server_network
monitored_vm2_port:
type: cloudify.openstack.nodes.Port
properties:
openstack_config: *openstack_config
relationships:
- type: cloudify.relationships.contained_in
target: proxy_server_network
monitored_vm1_host:
type: cloudify.openstack.nodes.Server
properties:
image: { get_input: image }
flavor: { get_input: flavor }
resource_id: { concat: ['monitored_vm1-', { get_input: client_name }] }
agent_config:
user: { get_input: agent_user }
key: { get_property: [ keypair, private_key_path ] }
interfaces:
cloudify.interfaces.monitoring_agent:
install:
implementation: diamond.diamond_agent.tasks.install
inputs:
diamond_config:
interval: 10
start: diamond.diamond_agent.tasks.start
stop: diamond.diamond_agent.tasks.stop
uninstall: diamond.diamond_agent.tasks.uninstall
cloudify.interfaces.monitoring:
start:
implementation: diamond.diamond_agent.tasks.add_collectors
inputs:
collectors_config:
NetworkCollector: {}
relationships:
- type: cloudify.openstack.server_connected_to_port
target: monitored_vm1_port
- type: cloudify.openstack.server_connected_to_keypair
target: keypair
monitored_vm2_host:
type: cloudify.openstack.nodes.Server
properties:
image: { get_input: image }
flavor: { get_input: flavor }
resource_id: { concat: ['monitored_vm2-', { get_input: client_name }] }
agent_config:
user: { get_input: agent_user }
key: { get_property: [ keypair, private_key_path ] }
interfaces:
cloudify.interfaces.monitoring_agent:
install:
implementation: diamond.diamond_agent.tasks.install
inputs:
diamond_config:
interval: 10
start: diamond.diamond_agent.tasks.start
stop: diamond.diamond_agent.tasks.stop
uninstall: diamond.diamond_agent.tasks.uninstall
cloudify.interfaces.monitoring:
start:
implementation: diamond.diamond_agent.tasks.add_collectors
inputs:
collectors_config:
NetworkCollector: {}
relationships:
- type: cloudify.openstack.server_connected_to_port
target: monitored_vm2_port
- type: cloudify.openstack.server_connected_to_keypair
target: keypair
groups:
vm_group:
members: [monitored_vm1_host, monitored_vm2_host]
scale_up_group:
members: [monitored_vm1_host, monitored_vm2_host]
policies:
auto_scale_up:
type: scale_policy_type
properties:
policy_operates_on_group: true
scale_limit: 2 # max additional instances
scale_direction: '<'
scale_threshold: 31457280
service_selector: .*monitored_vm1_host.*network.eth0.rx.bit
cooldown_time: 60
triggers:
execute_scale_workflow:
type: cloudify.policies.triggers.execute_workflow
parameters:
workflow: scale
workflow_parameters:
delta: 1
scalable_entity_name: vm_group
scale_compute: true
policies:
vm_group_scale_policy:
type: cloudify.policies.scaling
properties:
default_instances: 1
targets: [vm_group]
So the blueprint gets deployed correctly, and scale workflow is being triggered according to specified condition (traffic on the VM's interface), but it fails during creation of the new VMs instances with following errors:
2019-11-18 14:54:46,591:ERROR: Task nova_plugin.server.create[f736f81c-7f8c-4f82-a280-8352c1d01bff] raised:
Traceback (most recent call last):
(...)
NonRecoverableError: Port 3b727b5e-a2ec-47cc-b711-37cb80a7b4e5 is still in use. [status_code=409]
Looks like Cloudify is trying to spawn new instances using existing ports, weird.
So I thought, maybe I should explicitly place VM's ports in the scaling group as well, to replicate them along with VMs. Tried it like this:
vm_group:
members: [monitored_vm1_host, monitored_vm1_port, monitored_vm2_host, monitored_vm2_port]
But in that case I get an error regarding some missing objects relationships, already at blueprint verification stage:
Invalid blueprint - Node 'monitored_vm1_host' and 'monitored_vm1_port' belong to some shared group but they are not contained in any shared node, nor is any ancestor node of theirs.
in: /opt/manager/resources/blueprint-with-scaling-d79fed3d-0b3b-4459-a851-fedd9ecf50c6/blueprint-with-scaling.yaml
I've gone through documentation and any examples I could find (there are not many), but they're unclear to me.
How can I get it scale correctly?
You got the first error as you said because Cloudify tried to scale the VM and connect it to the port that was already bound to the first VM.
The second error means that you cannot scale the port if it does not depend on a node that is also scaled, this is to avoid the scale of resources that can't be scaled.
The solution for this would be, to have a node of type cloudify.nodes.Root and connect to it by relationship the port, if the port depends on this node and this node will be part of the scale group you will be able to scale.
Your blueprint will have something like this:
my_relationship_node:
type: cloudify.nodes.Root
port:
type: cloudify.openstack.nodes.Port
properties:
openstack_config: *openstack_config
relationships:
- type: cloudify.relationships.connected_to
target: public_network
- type: cloudify.relationships.depends_on
target: public_subnet
- type: cloudify.openstack.port_connected_to_security_group
target: security_group
- type: cloudify.openstack.port_connected_to_floating_ip
target: ip
- type: cloudify.relationships.contained_in
target: my_relationship_node
I hope it helps.
I am trying to create a HEAT template that will use 'allowed_address_pairs' and neutron ports to support the concept of a virtual IP address shared between instances for an application similar to VRRP.
I've followed the examples from http://superuser.openstack.org/articles/implementing-high-availability-instances-with-neutron-using-vrrp and from https://github.com/nvpnathan/heat/blob/master/allowed-address-pairs.yaml to come up with my own template to achieve this, and it works great for a single virtual IP address.
Here is what that template looks like:
heat_template_version: 2013-05-23
description: Simple template using allowed_address_pairs for a virtual IP
parameters:
image:
type: string
label: Image name or ID
description: Image to be used for compute instance
default: "cirros"
flavor:
type: string
label: Flavor
description: Type of instance (flavor) to be used
default: "t1.small"
key:
type: string
label: Key name
description: Name of key-pair to be used for compute instance
default: "mykey"
ext_network:
type: string
label: External network name or ID
description: External network that can assign a floating IP
default: "provider"
test_virtual_ip:
type: string
label: Virtual IP address
description: Virtual IP address that can be used on different instances
default: "192.168.10.101"
resources:
# Create the internal test network
test_net:
type: OS::Neutron::Net
properties:
admin_state_up: true
name: test_net
# Create a subnet on the test network
test_subnet:
type: OS::Neutron::Subnet
properties:
name: test_subnet
cidr: 192.168.10.2/24
enable_dhcp: true
allocation_pools: [{end: 192.168.10.99, start: 192.168.10.10}]
gateway_ip: 192.168.10.1
network_id: { get_resource: test_net }
# Create router for the test network
test_router:
type: OS::Neutron::Router
properties:
admin_state_up: true
name: test_router
external_gateway_info: { "network": { get_param: ext_network }}
# Create router interface and attach to subnet
test_router_itf:
type: OS::Neutron::RouterInterface
properties:
router_id: { get_resource: test_router }
subnet_id: { get_resource: test_subnet }
# Create extra port for a virtual IP address
test_vip_port:
type: OS::Neutron::Port
properties:
network_id: { get_resource: test_net }
fixed_ips:
- ip_address: { get_param: test_virtual_ip }
# Create instance ports that have an internal IP and the virtual IP
instance1_test_vip_port:
type: OS::Neutron::Port
properties:
admin_state_up: true
network_id: { get_resource: test_net }
allowed_address_pairs:
- ip_address: { get_param: test_virtual_ip}
security_groups:
- default
# Create instances
test_instance_1:
type: OS::Nova::Server
properties:
name: instance1
image: { get_param: image }
flavor: { get_param: flavor }
key_name: { get_param: key }
networks:
- port: { get_resource: instance1_test_vip_port }
user_data_format: RAW
user_data: |
#cloud-config
password: mysecret
chpasswd: { expire: False }
ssh_pwauth: True
final_message: "The system is up after $UPTIME sec"
outputs:
instance1_ip:
description: IP address of the first instance
value: { get_attr: [test_instance_1, first_address] }
So far so good. Now I need to take this to the next level and assign multiple IP addresses that can be used as virtual IPs within an instance. The problem is that it is not known in advance how many will be needed when the instance is launched, so it needs to be a parameter and cannot simply be hard-coded as
- ip_address: {get_param: ip1}
- ip_address: {get_param: ip2}
and so on
In other words, the parameter test_virtual_ip needs to be a list of IP addresses rather than a single IP address, e.g. "191.168.10.101, 192.168.10.102, 192.168.10.103"
This impacts the definitions for test_vip_port and instance1_test_vip_port, but I can't figure out the correct syntax.
I tried this:
# Create extra port for a virtual IP address
test_vip_port:
type: OS::Neutron::Port
properties:
network_id: { get_resource: test_net }
fixed_ips: [{ get_param: test_virtual_ip }]
# Create instance ports that have an internal IP and the virtual IP
instance1_test_vip_port:
type: OS::Neutron::Port
properties:
admin_state_up: true
network_id: { get_resource: test_net }
allowed_address_pairs: [{ get_param: test_virtual_ip}]
security_groups:
- default
But get error "unicode object has no attribute get" when I try to launch the stack.
What is the proper syntax for providing a list of IP addresses as a parameter to the OS::Neutron::Port::fixed_ips and OS::Neutron::Port::allowed_address_pairs ?
The only solution I was able to get to work was to use the repeat/for_each construct and define the parameter as a comma_delimited_list as follows:
test_virtual_ip:
type: comma_delimited_list
label: Virtual IP address
description: Virtual IP address that can be used on different instances
default: "192.168.10.101,192.168.10.102"
test_vip_port:
type: OS::Neutron::Port
properties:
network_id: { get_resource: test_net }
fixed_ips:
repeat:
for_each:
<%ipaddr%>: {get_param: test_virtual_ip}
template:
ip_address: <%ipaddr%>
A couple of details for this to work:
Your heat template version must support the repeat/for_each construct, I used heat_template_version: 2016-04-08
Don't include any spaces in the list of IP addresses or you will get validation errors.
firewall_rules:
- { get_resource: heat_firewall_tcp_22 }
- { get_resource: heat_firewall_tcp_43 }
- { get_resource: heat_firewall_tcp_53 }
- { get_resource: heat_firewall_tcp_80 }
- { get_resource: heat_firewall_tcp_443 }
This works fine for multiple entries type: OS::Neutron::FirewallPolicy
- { get_resource: heat_firewall_pol_web_1 }
- { get_resource: heat_firewall_pol_dns_1 }
- { get_resource: fw_pol_ssh_1 }
This does not work throwing expecting some sort of string value error for
type: OS::Neutron::Firewall
I am guessing there is not any general standard for formatting multiple entries in yaml?
I have configured 2-Node Openstack(Icehouse) setup and heat is also configured. when creating instance using HOT template it is successfully launched. But when I'm trying to create the flat network using my yml file it shows below error-
"Unable to create the network. No tenant network is available for allocation"
heat_template_version: 2013-05-23
description: Simple template to deploy a single compute instance
resources:
provider_01:
type: OS::Neutron::ProviderNet
properties:
physical_network: physnet2
shared: true
network_type: flat
network_01:
type: OS::Neutron::Net
properties:
admin_state_up: true
name: External2
shared: true
#admin tenant id
tenant_id: 6ec23610836048ddb8f9294dbf89a41e
subnet_01:
type: OS::Neutron::Subnet
properties:
name: Subnet2
network_id: { get_resource: network_01 }
cidr: 192.168.56.0/24
gateway_ip: 192.168.56.1
allocation_pools: [{"start": 192.168.56.50, "end": 192.168.56.70}]
enable_dhcp: true
port_01:
type: OS::Neutron::Port
properties:
admin_state_up: true
network_id: { get_resource: network_01 }
#security_groups: "default"
heat_template_version: 2014-10-16
description: Template to create a tenant network along with router config
parameters:
ImageId:
type: string
label: cirros-0.3.2-x86_64
description: cirros-0.3.2-x86_64
resources:
demo-net:
type: OS::Neutron::Net
properties:
name: demo-net
demo-subnet:
type: OS::Neutron::Subnet
properties:
name: demo-subnet
network_id: { get_resource: demo-net }
cidr: 10.10.0.0/24
gateway_ip: 10.10.0.1
my_instance:
type: OS::Nova::Server
properties:
name: "demo_test_nw_01"
image: { get_param: ImageId }
flavor: "m1.tiny"
networks:
- network : { get_resource: demo-net }