9dadbfdc6863d883604e8264eabbf56b5ad2c916
java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/impl/LandscapeServiceImpl.java
| ... | ... | @@ -1713,7 +1713,7 @@ public class LandscapeServiceImpl implements LandscapeService { |
| 1713 | 1713 | .setRegion(region) |
| 1714 | 1714 | .setPathPrefixForShardingKey(RemoteServiceMappingConstants.pathPrefixForShardingKey) |
| 1715 | 1715 | .setShardingKeys(shardingKeys) |
| 1716 | - .setReplicaset(applicationReplicaSet) |
|
| 1716 | + .setReplicaSet(applicationReplicaSet) |
|
| 1717 | 1717 | .setShardName(shardName) |
| 1718 | 1718 | .build() |
| 1719 | 1719 | .run(); |
| ... | ... | @@ -1735,7 +1735,7 @@ public class LandscapeServiceImpl implements LandscapeService { |
| 1735 | 1735 | .setRegion(region) |
| 1736 | 1736 | .setPathPrefixForShardingKey(RemoteServiceMappingConstants.pathPrefixForShardingKey) |
| 1737 | 1737 | .setShardingKeys(shardingkeys) |
| 1738 | - .setReplicaset(applicationReplicaSet) |
|
| 1738 | + .setReplicaSet(applicationReplicaSet) |
|
| 1739 | 1739 | .setShardName(shardName) |
| 1740 | 1740 | .build() |
| 1741 | 1741 | .run(); |
| ... | ... | @@ -1768,7 +1768,7 @@ public class LandscapeServiceImpl implements LandscapeService { |
| 1768 | 1768 | .setLandscape(getLandscape()) |
| 1769 | 1769 | .setTargetGroupNamePrefix(LandscapeService.SAILING_TARGET_GROUP_NAME_PREFIX) |
| 1770 | 1770 | .setShardingKeys(shardingkeys) |
| 1771 | - .setReplicaset(applicationReplicaSet) |
|
| 1771 | + .setReplicaSet(applicationReplicaSet) |
|
| 1772 | 1772 | .setRegion(region) |
| 1773 | 1773 | .setPathPrefixForShardingKey(RemoteServiceMappingConstants.pathPrefixForShardingKey) |
| 1774 | 1774 | .setShardName(shardName) |
java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/AwsLandscapeImpl.java
| ... | ... | @@ -341,6 +341,12 @@ public class AwsLandscapeImpl<ShardingKey> implements AwsLandscape<ShardingKey> |
| 341 | 341 | return result; |
| 342 | 342 | } |
| 343 | 343 | |
| 344 | + private Subnet getSubnetForAvailabilityZoneInSameVpcAsSecurityGroup(AwsAvailabilityZone az, SecurityGroup securityGroup, Region region) { |
|
| 345 | + final Ec2Client ec2Client = getEc2Client(region); |
|
| 346 | + final String vpcId = ec2Client.describeSecurityGroups(b->b.groupIds(securityGroup.getId())).securityGroups().iterator().next().vpcId(); |
|
| 347 | + return ec2Client.describeSubnets(b->b.filters(Filter.builder().name("vpc-id").values(vpcId).build())).subnets().iterator().next(); |
|
| 348 | + } |
|
| 349 | + |
|
| 344 | 350 | private <MetricsT extends ApplicationProcessMetrics, ProcessT extends ApplicationProcess<ShardingKey, MetricsT, ProcessT>> |
| 345 | 351 | Listener createLoadBalancerHttpListener(ApplicationLoadBalancer<ShardingKey> alb) { |
| 346 | 352 | return getLoadBalancingClient(getRegion(alb.getRegion())) |
| ... | ... | @@ -504,6 +510,11 @@ public class AwsLandscapeImpl<ShardingKey> implements AwsLandscape<ShardingKey> |
| 504 | 510 | |
| 505 | 511 | /** |
| 506 | 512 | * Grabs all subnets that are default subnet for any of the availability zones specified |
| 513 | + * <p> |
|
| 514 | + * |
|
| 515 | + * FIXME bug5838: for a non-default VPC its subnets won't be the default subnets for their AZs either. Hence, we |
|
| 516 | + * need to get the VPC-ID, either immediately or through a security group whose |
|
| 517 | + * {@link software.amazon.awssdk.services.ec2.model.SecurityGroup#vpcId() VPC-ID} could be used |
|
| 507 | 518 | */ |
| 508 | 519 | private Iterable<Subnet> getSubnetsForAvailabilityZones(Region region, Iterable<AwsAvailabilityZone> azs) { |
| 509 | 520 | return Util.filter(getEc2Client(region).describeSubnets().subnets(), subnet -> subnet.defaultForAz() |
| ... | ... | @@ -934,14 +945,8 @@ public class AwsLandscapeImpl<ShardingKey> implements AwsLandscape<ShardingKey> |
| 934 | 945 | .instanceType(instanceType).keyName(keyName) |
| 935 | 946 | .placement(Placement.builder().availabilityZone(az.getName()).build()) |
| 936 | 947 | .securityGroupIds(Util.mapToArrayList(securityGroups, SecurityGroup::getId)); |
| 937 | - final List<software.amazon.awssdk.services.ec2.model.SecurityGroup> awsSecurityGroups = ec2Client.describeSecurityGroups( |
|
| 938 | - b->b.groupIds(Util.asList(Util.map(securityGroups, SecurityGroup::getId)))).securityGroups(); |
|
| 939 | - ec2Client.describeSubnets().subnets().stream().filter( |
|
| 940 | - subnet-> |
|
| 941 | - subnet.availabilityZoneId().equals(az.getId()) && |
|
| 942 | - subnet.vpcId().equals(awsSecurityGroups.iterator().next().vpcId())) |
|
| 943 | - .findFirst() |
|
| 944 | - .map(subnet->runInstancesRequestBuilder.subnetId(subnet.subnetId())); |
|
| 948 | + runInstancesRequestBuilder.subnetId(getSubnetForAvailabilityZoneInSameVpcAsSecurityGroup( |
|
| 949 | + az, securityGroups.iterator().next(), getRegion(az.getRegion())).subnetId()); |
|
| 945 | 950 | if (userData != null) { |
| 946 | 951 | runInstancesRequestBuilder.userData(Base64.getEncoder().encodeToString(String.join("\n", userData).getBytes())); |
| 947 | 952 | } |
| ... | ... | @@ -1941,18 +1946,20 @@ public class AwsLandscapeImpl<ShardingKey> implements AwsLandscape<ShardingKey> |
| 1941 | 1946 | String imageId, AwsApplicationConfiguration<ShardingKey, MetricsT, ProcessT> replicaConfiguration, |
| 1942 | 1947 | int minReplicas, int maxReplicas, int maxRequestsPerTarget) { |
| 1943 | 1948 | logger.info("Creating launch configuration for replica set "+replicaSetName); |
| 1944 | - final AutoScalingClient autoScalingClient = getAutoScalingClient(getRegion(region)); |
|
| 1949 | + final Region awsRegion = getRegion(region); |
|
| 1950 | + final AutoScalingClient autoScalingClient = getAutoScalingClient(awsRegion); |
|
| 1945 | 1951 | final String releaseName = replicaConfiguration.getRelease().map(r->r.getName()).orElse("UnknownRelease"); |
| 1946 | 1952 | final String launchConfigurationName = getLaunchConfigurationName(replicaSetName, releaseName); |
| 1947 | 1953 | final String autoScalingGroupName = getAutoScalingGroupName(replicaSetName); |
| 1948 | 1954 | final Iterable<AwsAvailabilityZone> availabilityZones = getAvailabilityZones(region); |
| 1955 | + final SecurityGroup securityGroup = getDefaultSecurityGroupForApplicationHosts(region); |
|
| 1949 | 1956 | final int instanceWarmupTimeInSeconds = (int) Duration.ONE_MINUTE.times(3).asSeconds(); |
| 1950 | 1957 | autoScalingClient.createLaunchConfiguration(b->b |
| 1951 | 1958 | .launchConfigurationName(launchConfigurationName) |
| 1952 | 1959 | .keyName(keyName) |
| 1953 | 1960 | .imageId(imageId) |
| 1954 | 1961 | .instanceMonitoring(i->i.enabled(true)) |
| 1955 | - .securityGroups(getDefaultSecurityGroupForApplicationHosts(region).getId()) |
|
| 1962 | + .securityGroups(securityGroup.getId()) |
|
| 1956 | 1963 | .userData(Base64.getEncoder().encodeToString(replicaConfiguration.getAsEnvironmentVariableAssignments().getBytes())) |
| 1957 | 1964 | .instanceType(instanceType.toString())); |
| 1958 | 1965 | logger.info("Creating auto-scaling group for replica set "+replicaSetName); |
| ... | ... | @@ -1962,7 +1969,8 @@ public class AwsLandscapeImpl<ShardingKey> implements AwsLandscape<ShardingKey> |
| 1962 | 1969 | .maxSize(maxReplicas) |
| 1963 | 1970 | .healthCheckGracePeriod(instanceWarmupTimeInSeconds) |
| 1964 | 1971 | .autoScalingGroupName(autoScalingGroupName) |
| 1965 | - .availabilityZones(Util.toArray(Util.map(availabilityZones, az->az.getName()), new String[3])) |
|
| 1972 | + .vpcZoneIdentifier(Util.joinStrings(",", Util.map(availabilityZones, |
|
| 1973 | + az->getSubnetForAvailabilityZoneInSameVpcAsSecurityGroup(az, securityGroup, awsRegion)))) |
|
| 1966 | 1974 | .targetGroupARNs(publicTargetGroup.getTargetGroupArn()) |
| 1967 | 1975 | .launchConfigurationName(launchConfigurationName); |
| 1968 | 1976 | tags.ifPresent(t->{ |
java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/orchestration/ShardProcedure.java
| ... | ... | @@ -54,8 +54,8 @@ implements ProcedureCreatingLoadBalancerMapping<ShardingKey> { |
| 54 | 54 | protected final ShardingKey SHARDING_KEY_UNUSED_BY_ANY_APPLICATION = (ShardingKey) "lauycaluy3cla3yrclaurlIYQL8"; |
| 55 | 55 | protected final String shardName; |
| 56 | 56 | final protected Set<ShardingKey> shardingKeys; |
| 57 | - final AwsApplicationReplicaSet<ShardingKey, MetricsT, ProcessT> replicaSet; |
|
| 58 | - final Region region; |
|
| 57 | + final protected AwsApplicationReplicaSet<ShardingKey, MetricsT, ProcessT> replicaSet; |
|
| 58 | + final protected Region region; |
|
| 59 | 59 | private final String pathPrefixForShardingKey; |
| 60 | 60 | |
| 61 | 61 | protected ShardProcedure(BuilderImpl<?,?, ShardingKey, MetricsT, ProcessT> builder) throws Exception { |
| ... | ... | @@ -82,7 +82,7 @@ implements ProcedureCreatingLoadBalancerMapping<ShardingKey> { |
| 82 | 82 | |
| 83 | 83 | BuilderT setShardingKeys(Set<ShardingKey> shardingkeys); |
| 84 | 84 | |
| 85 | - BuilderT setReplicaset(AwsApplicationReplicaSet<ShardingKey, MetricsT, ProcessT> replicaset); |
|
| 85 | + BuilderT setReplicaSet(AwsApplicationReplicaSet<ShardingKey, MetricsT, ProcessT> replicaset); |
|
| 86 | 86 | |
| 87 | 87 | BuilderT setRegion(Region region); |
| 88 | 88 | } |
| ... | ... | @@ -122,7 +122,7 @@ implements ProcedureCreatingLoadBalancerMapping<ShardingKey> { |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | 124 | @Override |
| 125 | - public BuilderT setReplicaset(AwsApplicationReplicaSet<ShardingKey, MetricsT, ProcessT> replicaset) { |
|
| 125 | + public BuilderT setReplicaSet(AwsApplicationReplicaSet<ShardingKey, MetricsT, ProcessT> replicaset) { |
|
| 126 | 126 | this.replicaSet = replicaset; |
| 127 | 127 | return self(); |
| 128 | 128 | } |
wiki/info/landscape/amazon-ec2.md
| ... | ... | @@ -194,7 +194,7 @@ In our default region ``eu-west-1`` there are four Amazon Machine Image (AMI) ty |
| 194 | 194 | |
| 195 | 195 | The SAP Sailing Analytics image is used to launch new instances, shared or dedicated, that host one or more Sailing Analytics application processes. The image contains an installation of the SAP JVM 8 under /opt/sapjvm_8, an Apache httpd service that is not currently used by default for reverse proxying / rewriting / logging activities, an initially empty directory ``/home/sailing/servers`` used to host default application process configurations, and an initialization script under ``/etc/init.d/sailing`` that handles the instance's initialization with a default application process from the EC2 instance's user data. Instructions for setting up such an image from scratch can be found [here](/wiki/info/landscape/creating-ec2-image-from-scratch). |
| 196 | 196 | |
| 197 | -The user data line ``image-upgrade`` will cause the image to ignore all application configuration data and only bring the new instance to an updated state. For this, the Git content under ``/home/sailing/code`` is brought to the latest master branch commit, a ``yum update`` is carried out to install all operating system package updates available, log directories and the ``/home/sailing/servers`` directory are cleared, and the ``root`` user's crontab is brought up to date from the Git ``configuration/crontab`` file. If the ``no-shutdown`` line is provided in the instance's user data, the instance will be left running. Otherwise, it will shut down which would be a good default for creating a new image. See also [Upgrading AMIs](#amazon-ec2-for-sap-sailing-analytics_automated-procedures_upgrading-amis) for procedures that automate much of this upgrade process. |
|
| 197 | +The user data line ``image-upgrade`` will cause the image to ignore all application configuration data and only bring the new instance to an updated state. For this, the Git content under ``/home/sailing/code`` is brought to the latest master branch commit, a ``yum update`` is carried out to install all operating system package updates available, log directories and the ``/home/sailing/servers`` directory are cleared, and the ``root`` user's crontab is brought up to date from the Git ``configuration/crontab`` file. If the ``no-shutdown`` line is provided in the instance's user data, the instance will be left running. Otherwise, it will shut down which would be a good default for creating a new image. See also procedures that automate much of this upgrade process. |
|
| 198 | 198 | |
| 199 | 199 | The MongoDB Live Replica Set NVMe image is used to scale out or upgrade existing MongoDB replica sets. It also reads the EC2 instance's user data during start-up and can be parameterized by the following variables: ``REPLICA_SET_NAME``, ``REPLICA_SET_PRIMARY``, ``REPLICA_SET_PRIORITY``, and ``REPLICA_SET_VOTES``. An example configuration could look like this: |
| 200 | 200 | ``` |