Application deployed to Docker Swarm is not connecting with MongoDB Replica Set - amazon-web-services

I have deployed my application using Docker Swarm with 3 machines.
MongoDB Replica Set is configured manually and its working as a service on Ubuntu machine.
I am trying to connect to my Backend application to MongoDB Replica Set but I am getting context deadline exceeded error. I am using Private-ip to connect since machines are in same AWS VPC. Port 27017 is open in the security group and can be used by VPC network IP.
/etc/hosts is correctly configured on every machine.
I am using Docker-Compose file to deploy the stack.
Replica Set is working fine. I have checked it with manually inserting few documents.
The picture will help readers to understand the context better.
Abbreviations
BE = Backend
FE = Frontend
Mac 1 = Machine 1
AZ-1 = Availability Zone 1
VPC = Virtual Private Cloud
My Guess:
Is it because Replica-Set in not in the Swarm Network and that's why its unable to connect ???
I am trying to fix this issue for quite sometime now and have not been successful yet. Help is required now.

I found the solution.
The problem was related to the names of the MongoDB replica instances.
The host name for first member is "host" : "10.0.0.223:27017"
The host name for second member is "host" : "node2:27017"
The host name for third member is "host" : "node3:27017"
Due to this inconsistency, the backend application was not able to connect to the replica set.
{
"_id" : "replica1",
"version" : 5,
"term" : 5,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "10.0.0.223:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "node2:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "node3:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
Solution
To solve this I reconfigured the replica set nodes with private IPs. Node that I have used Private IP for replica set configuration.
First ssh to primary machine. Login to mongo primary node shell and execute the following commands to change the host entry for 2nd mongo node in JSON.
> cfg = rs.conf()
> cfg.members[2].host = "10.0.5.242:27017" (Private IP of second mongodb instance)
> rs.reconfig(cfg)
Did the same for 3rd mongo entry in JSON.
Here is the link to change the hostname in Replica Set.
https://docs.mongodb.com/manual/tutorial/change-hostnames-in-a-replica-set/
Another Solution:
If your MongoDB deployment is all fine and everything is set up properly, but still you are unable to connect to the DB, try to Change the Primary DB Instance.
ssh to primary machine.
Login to mongo primary node shell and execute this commands
replica:PRIMARY>rs.stepDown(120). This will make your other instance Primary and your current instance Secondary.
I experienced this problem and after continuous hit and try for 3 days, this solution worked for me.
Hope this would help readers to solve similar problem.

Related

How can I let Kibana read custom index for metric?

I deployed Elasticsearch and Kibana 7.10.1. And I am streaming cloudwatch metrics data (raw json) to Elasticsearch.
The metric raw data format looks like:
{
"metric_stream_name" : "metric-stream-elk",
"account_id" : "264100014405",
"region" : "ap-southeast-2",
"namespace" : "AWS/DynamoDB",
"metric_name" : "ReturnedRecordsCount",
"dimensions" : {
"Operation" : "GetRecords",
"StreamLabel" : "2021-06-18T01:12:31.851",
"TableName" : "dev-dms-iac-events"
},
"timestamp" : 1624924620000,
"value" : {
"count" : 121,
"sum" : 0,
"max" : 0,
"min" : 0
},
"unit" : "Count"
}
I can see that these raw data are saved in Elasitcsearch with a custom index name aws-metrics-YYYY-MM-DD. Now how can I let Kibana read metrics from this index?
I don't want to use metricbeat because it queries metrics from AWS. My event flow is streaming AWS metrics to Elasticsearch. How can I achieve that?

AWS Datapipeline : moving data from RDS database(postgres) to Redshift using pipeline

Basically i am trying to transfer data from postgres to redshift using aws datapipeline and the process i am following
Write a pipeline(CopyActivity) that moves data from postgres to s3
Write a pipeline(RedShiftCopyActivity) that moves data from s3 to redshift
So in my case both are working perfectly with the pipelines i wrote, but the problem is the data was duplicating in the Redshift database
For example below is the data from postgres database in a table called company
After the successful run of s3 to redshift(RedShiftCopyActivity) pipeline the data was copied but it was duplicated as below
below is the some of the definition part from RedShiftCopyActivity(S3 to Redshift) pipeline
pipeline_definition = [{
"id":"redshift_database_instance_output",
"name":"redshift_database_instance_output",
"fields":[
{
"key" : "database",
"refValue" : "RedshiftDatabaseId_S34X5",
},
{
"key" : "primaryKeys",
"stringValue" : "id",
},
{
"key" : "type",
"stringValue" : "RedshiftDataNode",
},
{
"key" : "tableName",
"stringValue" : "company",
},
{
"key" : "schedule",
"refValue" : "DefaultScheduleTime",
},
{
"key" : "schemaName",
"stringValue" : RedShiftSchemaName,
},
]
},
{
"id":"CopyS3ToRedshift",
"name":"CopyS3ToRedshift",
"fields":[
{
"key" : "output",
"refValue" : "redshift_database_instance_output",
},
{
"key" : "input",
"refValue" : "s3_input_data",
},
{
"key" : "runsOn",
"refValue" : "ResourceId_z9RNH",
},
{
"key" : "type",
"stringValue" : "RedshiftCopyActivity",
},
{
"key" : "insertMode",
"stringValue" : "KEEP_EXISTING",
},
{
"key" : "schedule",
"refValue" : "DefaultScheduleTime",
},
]
},]
So according to the docs of RedShitCopyActivity we need to use insertMode to describe how the data should behave(inserted/updated/deleted) when copying to database table as below
insertMode : Determines what AWS Data Pipeline does with pre-existing data in the target table that overlaps with rows in the data to be loaded. Valid values are KEEP_EXISTING, OVERWRITE_EXISTING, TRUNCATE and APPEND. KEEP_EXISTING adds new rows to the table, while leaving any existing rows unmodified. KEEP_EXISTING and OVERWRITE_EXISTING use the primary key, sort, and distribution keys to identify which incoming rows to match with existing rows, according to the information provided in Updating and inserting new data in the Amazon Redshift Database Developer Guide. TRUNCATE deletes all the data in the destination table before writing the new data. APPEND will add all records to the end of the Redshift table. APPEND does not require a primary, distribution key, or sort key so items that may be potential duplicates may be appended.
So what my requirements are
When copying from postgres (infact data is in s3 now) to Redshift database if it found already existing rows then just update it
If it founds new records from s3 then create new records in Redshift
But for me even though i have used KEEP_EXISTING or OVERWRITE_EXISTING, the data was just repeating over and over again as shown in the above redshift database picture
So finally how to achieve my requirements ? are there still any tweaks or settings to add to my configuration ?
Edit
Table(company) definition from redshift
If you want to avoid duplication , you must define Primary key in redshift and also set myInsertMode as "OVERWRITE_EXISTING" .

Redis Multi-AZ feature in CloudFormation

I'm designing a template which includes a Redis service and I would like to enable Multi-AZ feature in Redis such that upon the primary cluster failure, read replica can be promoted to primary. I looked in the CloudFormation documentation but I couldn't find this feature i.e. Multi-AZ. It is available for RDS service but not for Redis. Can I know how I can include the feature for redis such AWS take cares of the automatic failover ?
Source:
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-cache-cluster.html
The list of properties that are available for the elastic cache are listed below.
"AutoMinorVersionUpgrade" : Boolean,
"AZMode" : String,
"CacheNodeType" : String,
"CacheParameterGroupName" : String,
"CacheSecurityGroupNames" : [ String, ... ],
"CacheSubnetGroupName" : String,
"ClusterName" : String,
"Engine" : String,
"EngineVersion" : String,
"NotificationTopicArn" : String,
"Port" : Integer,
"PreferredAvailabilityZone" : String,
"PreferredAvailabilityZones" : [String, ... ],
"PreferredMaintenanceWindow" : String,
"SnapshotArns" : [String, ... ],
"SnapshotName" : String,
"SnapshotRetentionLimit" : Integer,
"SnapshotWindow" : String,
"Tags" : [Resource Tag, ...],
"VpcSecurityGroupIds" : [String, ...]
This are the two ways you can set Redis to use Multi Az programatically.
Using CLI
aws elasticache modify-replication-group \
--replication-group-id myReplGroup \
--automatic-failover-enabled
Using Elasticache API
https://elasticache.us-west-2.amazonaws.com/
?Action=ModifyReplicationGroup
&AutoFailover=true
&ReplicationGroupId=myReplGroup
&Version=2015-02-02
&SignatureVersion=4
&SignatureMethod=HmacSHA256
&Timestamp=20140401T192317Z
&X-Amz-Credential=<credential>
This are some of the notes that you should read while selecting Multi Az for redis.
http://docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/AutoFailover.html#AutoFailover.Notes
For Cloud Formation below are the Properties:
{
"Type" : "AWS::ElastiCache::ReplicationGroup",
"Properties" : {
"AutomaticFailoverEnabled" : Boolean,
"AutoMinorVersionUpgrade" : Boolean,
"CacheNodeType" : String,
"CacheParameterGroupName" : String,
"CacheSecurityGroupNames" : [ String, ... ],
"CacheSubnetGroupName" : String,
"Engine" : String,
"EngineVersion" : String,
"NotificationTopicArn" : String,
"NumCacheClusters" : Integer,
"Port" : Integer,
"PreferredCacheClusterAZs" : [ String, ... ],
"PreferredMaintenanceWindow" : String,
"ReplicationGroupDescription" : String,
"SecurityGroupIds" : [ String, ... ],
"SnapshotArns" : [ String, ... ],
"SnapshotRetentionLimit" : Integer,
"SnapshotWindow" : String
}
}
You have to tweak this property for Multi Az
AutomaticFailoverEnabled
Indicates whether Multi-AZ is enabled. When Multi-AZ is enabled, a read-only replica is automatically promoted to a read-write primary cluster if the existing primary cluster fails. If you specify true, you must specify a value greater than 1 for the NumCacheNodes property. By default, AWS CloudFormation sets the value to true.
For more information about Multi-AZ, see Multi-AZ with Redis Replication Groups in the Amazon ElastiCache User Guide.
Note
You cannot enable automatic failover for Redis versions earlier than 2.8.6 or for T1 and T2 cache node types.
Required: No
Type: Boolean
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticache-replicationgroup.html

Can you connect a SqlActivity to a JdbcDatabase in Amazon Data Pipeline?

Using Amazon Data Pipeline, I'm trying to use a SqlActivity to execute some SQL on a non-Redshift data store (SnowflakeDB, for the curious). It seems like it should be possible to do that with a SqlActivity that uses a JdbcDatabase. My first warning was when the wysiwyg editor on Amazon didn't even let me try to create a JdbcDatabase, but I plowed on anyway and just wrote and uploaded a Json definition by hand, myself (here's the relevant bit):
{
"id" : "ExportToSnowflake",
"name" : "ExportToSnowflake",
"type" : "SqlActivity",
"schedule" : { "ref" : "DefaultSchedule" },
"database" : { "ref" : "SnowflakeDatabase" },
"dependsOn" : { "ref" : "ImportTickets" },
"script" : "COPY INTO ZENDESK_TICKETS_INCREMENTAL_PLAYGROUND FROM #zendesk_incremental_stage"
},
{
"id" : "SnowflakeDatabase",
"name" : "SnowflakeDatabase",
"type" : "JdbcDatabase",
"jdbcDriverClass" : "com.snowflake.client.jdbc.SnowflakeDriver",
"username" : "redacted",
"connectionString" : "jdbc:snowflake://redacted.snowflakecomputing.com:8080/?account=redacted&db=redacted&schema=PUBLIC&ssl=on",
"*password" : "redacted"
}
When I upload this into the designer, it refuses to activate, giving me this error message:
ERROR: 'database' values must be of type 'RedshiftDatabase'. Found values of type 'JdbcDatabase'
The rest of the pipeline definition works fine without any errors. I've confirmed that it activates and runs to success if I simply leave this step out.
I am unable to find a single mention on the entire Internet of someone actually using a JdbcDatabase from Data Pipeline. Does it just plain not work? Why is it even mentioned in the documentation if there's no way to actually use it? Or am I missing something? I'd love to know if this is a futile exercise before I blow more of the client's money trying to figure out what's going on.
In your JdbcDatabase you need to have the following property:
jdbcDriverJarUri: "[S3 path to the driver jar file]"

Generating consumer key and consumer secret in WSO2 API Manager

I want to integrate the WSO2 API Manager with a website so that the user doesn't need to login to the API Store.
From what I can see there is a stumbling block, in that the user needs to click on the 'Generate' button in the store in order to first generate the consumer key and secret.
Once this has been done then on it is possible to call the subscription API and generate token API as documented:
$ curl -b cookies http://localhost:9763/store/site/blocks/subscription/subscription-list/ajax/subscription-list.jag?action=getAllSubscriptions
{
"error" : false,
"subscriptions" : [
{
{
"sandRegenarateOption" : true,
"prodKey" : "2486e65cbac4e372fb319375744fb",
"subscriptions" : [
{
...
"prodConsumerSecret" : "Tx9i9WYu6_a3qqW08bF7jEG660",
"prodConsumerKey" : "VfS5r5u4rFhec2vVBlFosxRgcE",
"prodAuthorizedDomains" : "ALL"
...
}
],
...
"prodConsumerSecret" : "Tx9i9WYu6_a3qqW08bF7jEG660",
"prodConsumerKey" : "VfS5r5u4rFhec2vVBlFosxRgcE"
...
}
]
}
However until the 'Generate' button has been clicked in the browser, the values above are null
When I tried using the suggestion:
$ curl -X POST -b cookies http://localhost:9763/store/site/blocks/subscription/subscription-add/ajax/subscription-add.jag -d "action=generateApplicationKey&application=4&keytype=PRODUCTION&provider=admin&tier=Unlimited&version=0.1&callbackUrl=&authorizedDomains="
The server logs:
ERROR - APIStoreHostObject Error while obtaining the application access token for the application:4
org.wso2.carbon.apimgt.api.APIManagementException: Application should be approved before registering.
at org.wso2.carbon.apimgt.impl.APIConsumerImpl.requestApprovalForApplicationRegistration(APIConsumerImpl.java:1678)
at org.wso2.carbon.apimgt.impl.UserAwareAPIConsumer.requestApprovalForApplicationRegistration(UserAwareAPIConsumer.java:34)
at org.wso2.carbon.apimgt.hostobjects.APIStoreHostObject.jsFunction_getApplicationKey(APIStoreHostObject.java:649)
But according to the getApplications API it is approved already:
curl -b cookies http://localhost:9763/store/site/blocks/application/application-list/ajax/application-list.jag?action=getApplications
{
"applications" : [
...
{
"tier" : "Unlimited",
"status" : "APPROVED",
"callbackUrl" : "",
"name" : "app2",
"id" : 4,
"description" : ""
}
],
"error" : false
}
Any more thoughts ?
You can try the following REST invocation
curl -X POST -b cookies http://localhost:9763/store/site/blocks/subscription/subscription-add/ajax/subscription-add.jag -d "action=generateApplicationKey&application=DefaultApplication&keytype=PRODUCTION&provider=admin&tier=Unlimited&version=1.0.0&callbackUrl=&authorizedDomains="
I do not see any direct way to get that done. But you can make use of Store API exposed by wso2 API manger and retrieve all the subscription and from that you can filter the required ConsumerKey and ConsumerSecret.
I have tried this and worked pretty well to me :)
You need to promote before subscribing. You need to call "/site/blocks/life-cycles/ajax/life-cycles.jag" endpoint with "PUBLISHED" status and "updateStatus" action. Once it is in promoted state you can subscribe to it.