How to handle domain status of Amazon elasticsearch service? - amazon-web-services

I created an elasticsearch cluster and uploaded 45 GB of data.There, I tried to changed the access policy of the domain. The domain status has been showing "Processing" for last 24 hours. Is there any way to reset access policy and Why is the domain status still "Processing"?

Part of the response from AWS support to a similar question:
Any configuration change we spin up another set of instance and copy the data across to new search domain before we terminate previous set of instances.
So it might be that it's taking them a while to copy that data over and perform any other indexing operations on the new ES instance.

Related

Kibana health status is RED

I am using AWS ELK(amazon managed elastic) and my Kibana health status is red, trying to browse to the kibana URL i get "Kibana server is not ready yet".
I have tried to fix the problem but without luck, I think it all start when I changed my ELK settings from 1 availability zones with 1 instances to 2 Availability zones or another option is that I have streamed large amount of data in the last day.
As part of trials to fix the problem I returned to 1 availability zones with 1 instances but that didn't fix the problem.
Also I have Enabled the error logs and seen that I receive in cloudwatch:
"publishing cluster state with version [68816] failed for the
following nodes"
"failed to connect to node"
Any help solving this problem will help.
More info(about my current setup):
Domain status:Active
Elasticsearch version: 6.7
Availability zones:1
Instance type:r5.large.elasticsearch
Number of instances:1
Storage type:EBS
EBS volume type:General Purpose (SSD)
EBS volume size:1000 GB
Encryption at rest:Disabled
Node-to-node encryption:Disabled
Amazon Cognito for authentication:Disabled
Service software release:R20190724-P1
in the cluster health tab of the domain I can see:
Cluster status:green
MasterReachableFromNode:green
AutomatedSnapshotFailure:green
KibanaHealthyNodes:red
and in the InvalidHostHeaderRequests I have about 60% of requests that are InvalidHostHeaderRequests out of ElasticsearchRequests (but I guess that is unrelated):
CPUUtilization: is about 8%
JVMMemoryPressure: is about 20%
SysMemoryUtilization:98%
KibanaHealthyNodes is red possibly your kibana is down. Have you updated to AWS Elasticsearch v6.7 recently? Looks like the kibana needs to be restarted on the elasticsearch cluster for which AWS support team can help you with. Or in case you dont have support plan might be if you post on AWS forum someone from AWS can take a look and assist you with the same.
InvalidHostHeaderRequests will not cause the issue with kibana. AWS ES will throw this error when your application is trying to send the request on IPs of the nodes. Please check and use the domain endpoint in the request else this error will come up.
https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-managedomains.html

Trying to automatically register my EC2 instances in Route 53

I have approximately 40 Windows EC2 instances running at the moment. This number will start to grow substantially in the next few months. Each one is a t2.small Windows 2016 Server instance. Cost is starting to become an issue as the number increases. Each instance has its own Elastic IP address because when user Tom wants to access his machine he will use the DNS tom.mydomain.com.
tom.mydomain.com is registered in a Route53 hosted zone pointing to Elastic IP 22.33.44.55 which has been associated with Tom's EC2 instance.
Problem is that Tom only needs to use his machine 4 hours per day. When not using it he simply shuts the machine down. But... An Elastic IP that is pointing to a stopped instance costs almost as much per hour as a t1.micro instance in a running state.
So what I want to do is when Tom logs into AWS console and starts his EC2 instance, it will automatically register itself with Route53 against the DNS "tom.mydomain.com".
In short I want to do away with the need for Elastic IPs which are fast becoming a very substantial cost.
The tutorial Auto-Register EC2 Instance in AWS Route 53
looks like it does exactly what I want to do. The problem is the scripting is for Linux. I want to get it working for Windows. I have everything done down to step 6 in the tutorial but am stuck there. Any one get something similar to this working on Windows?
I would recommend:
Create a web-based front-end where your users can authenticate and request access to their Amazon EC2 instance
You could use Amazon Cognito for authentication and DynamoDB for data storage
Once the user authenticates, the service can:
Start their EC2 instance (if it was previously stopped)
Associate the random public IP address to the customer's domain name
Tell the user that the instance is now available
Users login to the instance and perform their work function
You then have some mechanism (I'm not sure what) that detects that they no longer need the instance, and then Stops the instance to save costs
The above process avoids assigning IAM credentials to your users. While IAM credentials are important for staff members who work on your AWS infrastructure, they should not be assigned to end-users of your service.
The process also avoids assigning IAM permissions to each EC2 instance. While the instances themselves could call Route 53 to update a record for their domain name, this requires an IAM Role to be assigned to the EC2 instance. If your users have access to the instance itself, this would potentially open a security hole where they could call Route 53 with incorrect data, such as assigning other users' domain names to their own instance.
It's worth mentioning that the above recommendations mirror the way that Amazon WorkSpaces operates — users authenticate, their instance is started and after a period of non-use the instance is stopped.
I will recommend use of cloudformation template. Cloudformation can create EC2 and then attach it to route53 url. So when tom like to use the EC2 instance, he have to run the stack in Cloudformation. Once he finished he have to go back to cloudformation and destroy the stack.
Yes Cloudformation would be a recommended approach. You can try cloudkast which is an online cloudformation template generator. It will make your task of creating cloudformation template very easy and effortless

Master Instance Group: Exceeded EC2 Instance Quota

I am getting this error Master Instance Group: Exceeded EC2 Instance Quota, when I create a new cluster on Amazon EMR with 1 Master node only or 1 Master and 2 Core nodes. However, there are no EC2 instances running on my account.
What should I do? I raised a ticket, asking if I can get a quicker solution here.
In your case I think you are trying to access a new region or new instance type, AWS sometimes does that when you are in free tier, they allow access to 2-3 regions or free instance types only. Then you have to request access from AWS by raising a case.
But in Normal scenario, this is what happens:
You may face an error like Exceeded EC2 Instance Quota while you are trying to spin up new instances either standalone or in cluster.
This error is caused because you have hit the limit on number of instances allowed in your AWS account.
This limit is region and instance size specific. To get rid of this error you will have to request Amazon to increase the EC2 instance limit.
Requesting a limit increase is simple. Below are the steps:
Most service limit increases can be requested through the AWS Support Center by choosing Create Case and then choosing Service Limit Increase.
Most service limits are specific to a particular AWS Region, so be sure to submit a request for each Region you plan to use. Many services support requesting multiple limit increases for the same service through one support case. After creating your first request, choose Add another request and then choose a new limit type or Region.

automatically start an EC2 instance when a request is made

I have website that I access very infrequently (sometimes 2/3 times a day and sometimes none)
I would like to automatically shutdown the instance as soon as no traffic happen (this would be possible when setting a cloudwatch alarm).
The current issue I have is that I would like to start the instance again as soon as there is a request on the website (I don't mind at all having to wait for the instance to come back online).
Is there any way of doing that? If yes how would that work technically?
DISCLAIMER: only some theoretical thoughts
Main idea: a landing page using S3 (static website), visiting this page will trigger an Lambda script.This Lambda script will launch the instance.
More details:
an Amazon S3 static website with a landing page + javascript to:
make a call to Amazon API Gateway
test if the instance is ready
redirect to proper page when everything is ready
maybe some url/javascript tricks to avoid the instance to be started by crawlers and bots, scanners etc
an Amazon API Gateway: only using to trigger an event for Amazon Lambda
an Amazon lambda script used for launching your instance, if is not running.
Depending on your needs, you can try to go serverless like here: https://gofore.com/en/going-serverless-with-amazon-s3-and-lambda/
You can use AutoScaling group. Set the scaling rules as per your need and that's it.
While adding the instance (scaling up) you can use 'Add' 1 instance and while removing the instance (scaling down) you can use 'Set to' 0 instance.
However keep in mind that when the instances are 0 and when the request comes in, that request will not be served but it can just trigger the scale up so that subsequent request can be served after the instance has warmed up.

How to make a HTTP call reaching all instances behind amazon AWS load balancer?

I have a web app which runs behind Amazon AWS Elastic Load Balancer with 3 instances attached. The app has a /refresh endpoint to reload reference data. It need to be run whenever new data is available, which happens several times a week.
What I have been doing is assigning public address to all instances, and do refresh independently (using ec2-url/refresh). I agree with Michael's answer on a different topic, EC2 instances behind ELB shouldn't allow direct public access. Now my problem is how can I make elb-url/refresh call reaching all instances behind the load balancer?
And it would be nice if I can collect HTTP responses from multiple instances. But I don't mind doing the refresh blindly for now.
one of the way I'd solve this problem is by
writing the data to an AWS s3 bucket
triggering a AWS Lambda function automatically from the s3 write
using AWS SDK to to identify the instances attached to the ELB from the Lambda function e.g. using boto3 from python or AWS Java SDK
call /refresh on individual instances from Lambda
ensuring when a new instance is created (due to autoscaling or deployment), it fetches the data from the s3 bucket during startup
ensuring that the private subnets the instances are in allows traffic from the subnets attached to the Lambda
ensuring that the security groups attached to the instances allow traffic from the security group attached to the Lambda
the key wins of this solution are
the process is fully automated from the instant the data is written to s3,
avoids data inconsistency due to autoscaling/deployment,
simple to maintain (you don't have to hardcode instance ip addresses anywhere),
you don't have to expose instances outside the VPC
highly available (AWS ensures the Lambda is invoked on s3 write, you don't worry about running a script in an instance and ensuring the instance is up and running)
hope this is useful.
While this may not be possible given the constraints of your application & circumstances, its worth noting that best practice application architecture for instances running behind an AWS ELB (particularly if they are part of an AutoScalingGroup) is ensure that the instances are not stateful.
The idea is to make it so that you can scale out by adding new instances, or scale-in by removing instances, without compromising data integrity or performance.
One option would be to change the application to store the results of the reference data reload into an off-instance data store, such as a cache or database (e.g. Elasticache or RDS), instead of in-memory.
If the application was able to do that, then you would only need to hit the refresh endpoint on a single server - it would reload the reference data, do whatever analysis and manipulation is required to store it efficiently in a fit-for-purpose way for the application, store it to the data store, and then all instances would have access to the refreshed data via the shared data store.
While there is a latency increase adding a round-trip to a data store, it is often well worth it for the consistency of the application - under your current model, if one server lags behind the others in refreshing the reference data, if the ELB is not using sticky sessions, requests via the ELB will return inconsistent data depending on which server they are allocated to.
You can't make these requests through the load balancer, So you will have to open up the security group of the instances to allow incoming traffic from source other than the ELB. That doesn't mean you need to open it to all direct traffic though. You could simply whitelist an IP address in the security group to allow requests from your specific computer.
If you don't want to add public IP addresses to these servers then you will need to run something like a curl command on an EC2 instance inside the VPC. In that case you would only need to open the security group to allow traffic from some server (or group of servers) that exist in the VPC.
I solved it differently, without opening up new traffic in security groups or resorting to external resources like S3. It's flexible in that it will dynamically notify instances added through ECS or ASG.
The ELB's Target Group offers a feature of periodic health check to ensure instances behind it are live. This is a URL that your server responds on. The endpoint can include a timestamp parameter of the most recent configuration. Every server in the TG will receive the health check ping within the configured Interval threshold. If the parameter to the ping changes it signals a refresh.
A URL may look like:
/is-alive?last-configuration=2019-08-27T23%3A50%3A23Z
Above I passed a UTC timestamp of 2019-08-27T23:50:23Z
A service receiving the request will check if the in-memory state is at least as recent as the timestamp parameter. If not, it will refresh its state and update the timestamp. The next health-check will result in a no-op since your state was refreshed.
Implementation notes
If refreshing the state can take more time than the interval window or the TG health timeout, you need to offload it to another thread to prevent concurrent updates or outright service disruption as the health-checks need to return promptly. Otherwise the node will be considered off-line.
If you are using traffic port for this purpose, make sure the URL is secured by making it impossible to guess. Anything publicly exposed can be subject to a DoS attack.
As you are using S3 you can automate your task by using the ObjectCreated notification for S3.
https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html
https://docs.aws.amazon.com/cli/latest/reference/s3api/put-bucket-notification.html
You can install AWS CLI and write a simple Bash script that will monitor that ObjectCreated notification. Start a Cron job that will look for the S3 notification for creation of new object.
Setup a condition in that script file to curl "http: //127.0.0.1/refresh" when the script file detects new object created in S3 it will curl the 127.0.0.1/refresh and done you don't have to do that manually each time.
I personally like the answer by #redoc, but wanted to give another alternative for anyone that is interested, which is a combination of his and the accepted answer. Using SEE object creation events, you can trigger a lambda, but instead of discovering the instances and calling them, which requires the lambda to be in the vpc, you could have the lambda use SSM (aka Systems Manager) to execute commands via a powershell or bash document on EC2 instances that are targeted via tags. The document would then call 127.0.0.1/reload like the accepted answer has. The benefit of this is that your lambda doesn't have to be in the vpc, and your EC2s don't need inbound rules to allow the traffic from lambda. The downside is that it requires the instances to have the SSM agent installed, which sounds like more work than it really is. There's AWS AMIs already optimized with SSM agent stuff, but installing it yourself in the user data is very simple. Another potential downside, depending on your use case, is that it uses an exponential ramp up for simultaneous executions, which means if you're targeting 20 instances, it runs one 1, then 2 at once, then 4 at once, then 8, until they are all done, or it reaches what you set for the max. This is because of the error recovery stuff it has built in. It doesn't want to destroy all your stuff if something is wrong, like slowly putting your weight on some ice.
You could make the call multiple times in rapid succession to call all the instances behind the Load Balancer. This would work because the AWS Load Balancers use round-robin without sticky sessions by default, meaning that each call handled by the Load Balancer is dispatched to the next EC2 Instance in the list of available instances. So if you're making rapid calls, you're likely to hit all the instances.
Another option is that if your EC2 instances are fairly stable, you can create a Target Group for each EC2 Instance, and then create a listener rule on your Load Balancer to target those single instance groups based on some criteria, such as a query argument, URL or header.