I'm trying to configure a Hadoop cluster, but to do so I needed the ip address of the namenode.
The cluster itself is being created by Vagrant, but I don't have the ip address until vagrant creates the instance in AWS.
So, I have the following Vagrantfile:
current_dir = File.dirname(__FILE__)
$master_script = <<SCRIPT
// will write a script to configure
SCRIPT
Vagrant.configure("2") do |config|
config.omnibus.chef_version = :latest
config.vm.provider :aws do |aws, override|
config.vm.box = "dummy"
aws.access_key_id = "MY_KEY"
aws.secret_access_key = "SECRET_KEY"
aws.keypair_name = "my_key"
aws.ami = "ami-7747d01e"
override.ssh.username = "ubuntu"
override.ssh.private_key_path = "#{current_dir}/my_key.pem"
end
config.vm.provider :virtualbox do |v|
config.vm.box = "precise64"
config.vm.box_url = "https://vagrantcloud.com/chef/ubuntu-13.04/version/1/provider/virtualbox.box"
v.customize ["modifyvm", :id, "--memory", "1024"]
end
config.vm.define :namenode do |namenode|
namenode.vm.box = "dummy"
namenode.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "cookbooks"
chef.roles_path = "roles"
chef.add_role "cluster"
end
namenode.vm.provision :hostmanager
namenode.vm.provision "shell", :inline => $master_script
end
config.vm.define :slave do |slave|
slave.vm.box = "dummy"
slave.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "cookbooks"
chef.roles_path = "roles"
chef.add_role "cluster"
end
slave.vm.provision :hostmanager
slave.vm.provision "shell", :inline => $master_script
end
end
I need to update the mapred-site.xml and core-site.xml files with the ip address of the namenode. How could I get the ip address of the namenode box so I can update the hadoop config files? Is there a better option in the cookbook that I can use to accomplish it?
Suppose I have 1 namenode and 5 slaves, the mapred-site.xml.erb template will look like:
<configuration>
<property>
<name>mapred.job.tracker</name>
<value>hdfs://<%= node[:ipaddress] %>:8021</value>
</property>
</configuration>
However, I needed that all the namenode and the slaves to have the ip address only of the namenode. How can I accomplish that in chef?
Either way will work for me, even though I prefer the chef solution.
You could:
1- Use the instance metadata service on the namenode instance to find out its own ip:
curl http://169.254.169.254/latest/meta-data/local-ipv4
see: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html
2- Tag the namenode (ex: HADOOP_ROLE=NAMENODE) and use AWS CLI on any instance to find the local ip of the namenode:
aws ec2 describe-instances \
--region=us-east-1 \
--filter "Name=tag:HADOOP_ROLE,Values=NAMENODE" \
--query='Reservations[*].Instances[*].PrivateIpAddress' \
--output=text
see: http://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html
Related
We've provisioned an Azure Redis Cache server using the Premium tier. The server is clustered, with 2 shards, and the server is configured to allow public access over the public internet through a firewall--allow-listing a set of known IPs.
Deploys of our Rails application two any of these known IPs fail with the error:
Redis::CannotConnectError: Redis client could not connect to any cluster nodes
Here is our Rails config:
# application.rb
if Rails.env.test?
config.cache_store = :redis_cache_store, {
url: config.nines[:redis_url],
expires_in: 90.minutes,
namespace: ENV['TEST_ENV_NUMBER'],
}
else
config.cache_store = :redis_store, {
namespace:ENV['TEST_ENV_NUMBER'],
cluster: [ Rails.application.config.nines[:redis_url] ],
replica: true, # allow reads from replicas
compress: true,
compress_threshold: 1024,
expires_in: 90.minutes
}
end
The config.nines[:redis_url] is set like this: rediss://:<pw>#<cache-name>.redis.cache.windows.net:6380/0
Then, we initialize the Redis connection in code like this:
if Rails.env.test?
::Redis.new :url => redis_url, :db => ENV['REDIS_DB']
else
::Redis.new(cluster: [ "#{redis_url}" ], db: ENV['REDIS_DB'])
end
We're using the redis-rb gem and redis-rails gem.
If anyone can point out what we're doing wrong, please do share!
Thank you User Peter Pan - Stack Overflow. Posting your suggestion as answer to help other community members.
You can try below code:
# Import the redis library for Ruby
require "redis"
# Create a redis client instance for connecting Azure Redis Cache
# At here, for enabling SSL, set the `:ssl` symbol with the
# symbol value `:true`, see https://github.com/redis/redis-rb#ssltls-support
redis = Redis.new(
:host => '<azure redis cache name>.redis.cache.windows.net',
:port => 6380,
:db => <the db index you selected like 10>,
:password => "<access key>",
:ssl => :true)
# Then, set key `foo` with value `bar` and return `OK`
status = redis.set('foo', 'bar')
puts status # => OK
# Get the value of key `foo`
foo = redis.get('foo')
puts foo # => bar
Reference: How to setup Azure Redis cache with Rails - Stack Overflow
Wondering why I can only have 1 stream listening on a specific port on sidekiq/redis/icecast Rails Stream app. My files are as following:
icecast.xml
<!-- You may have multiple <listener> elements -->
<listen-socket>
<port>35687</port>
<shoutcast-mount>/hiphop</shoutcast-mount>
<!-- <bind-address>127.0.0.1</bind-address> -->
<!-- <shoutcast-mount>/stream</shoutcast-mount> -->
</listen-socket>
<listen-socket>
<port>35690</port>
<shoutcast-mount>/rock</shoutcast-mount>
</listen-socket>
2 workers on rails
class RadioWorker
include Sidekiq::Worker
sidekiq_options :queue => :radioworker
def perform(*_args)
prev_song = nil
s = Shout.new # ruby-shout instance
s.mount = "/rock" # our mountpoint
s.charset = "UTF-8"
s.port = 35690 # the port we've specified earlier
s.host = 'localhost' # hostname
s.user = 'source' # credentials
s.pass = 'parolata'
s.format = Shout::MP3 # format is MP3
s.description = 'Geek Radio' # an arbitrary name
s.connect
class TestWorker
include Sidekiq::Worker
sidekiq_options :queue => :testworker
def perform(*_args)
prev_song = nil
s = Shout.new # ruby-shout instance
s.mount = "/hiphop" # our mountpoint
s.charset = "UTF-8"
s.port = 35687 # the port we've specified earlier
s.host = 'localhost' # hostname
s.user = 'source' # credentials
s.pass = 'parolata'
s.format = Shout::MP3 # format is MP3
s.description = 'Geek Radio' # an arbitrary name
s.connect
both workers have been set to perform async in initializer/sidekiq.rb
and I have the sidekiq queues defined in config/sidekiq.yml
:queues:
- ["radioworker", 1]
- ["testworker", 1]
Currently It seems as if on an instance of bundle exec sidekick -C config/sidekiq.yml I can only listen to 1 of the 2 streams. How can I have them both running at the same time and be able to listen to them?
Thanks in advance
All I had to do was run 2 sidekiq processes 1 running with the params -q radioworker and 1 running with -q testworker. Sorry if the problem description was vague.I was trying to run 2 processes with 1 thread each.Not 1 process with 2 threads. Thanks for the help
In rails 5, I need to configure the dynamodb feature. I have referred some blogs and tried to implement it. First in localhost it was running without any issue, but when I move to other new system or a server then it is showing an error like,
/home/NICHEPRO/shruthir/.rvm/gems/ruby-2.4.0/gems/aws-sdk-core-2.10.19/lib/aws-sdk-core/plugins/regional_endpoint.rb:34:in `after_initialize': missing region; use :region option or export region name to ENV['AWS_REGION'] (Aws::Errors::MissingRegionError)
from /home/NICHEPRO/shruthir/.rvm/gems/ruby-2.4.0/gems/aws-sdk-core-2.10.19/lib/seahorse/client/base.rb:84:in `block in after_initialize'
AWS gem is,
aws-sdk (2.10.19)
aws-sdk-core (2.10.19)
aws-sdk-resources (2.10.19)
Referred From:
https://assist-software.net/snippets/how-save-data-amazon-dynamodb-using-ruby-on-rails
Also I have tried to fix this by referring other blogs but I will get below error too,
Failed to open TCP connection to localhost:8080 (Connection refused - connect(2) for "localhost" port 8080)
How to solve this issue?
Hope you are using Dynamoid gem. In app/config/initializer add a new config file and add below code.
Dynamoid.configure do |config|
config.adapter = 'aws_sdk_v2' # This adapter establishes a connection to the DynamoDB servers using Amazon's own AWS gem.
config.access_key = (ENV['AWS_ACCESS_KEY_ID'] || APP_CONFIG[:aws_access_key_id])
config.secret_key = (ENV['AWS_SECRET_ACCESS_KEY'] || APP_CONFIG[:aws_secret_access_key])
config.region = (ENV['AWS_REGION'] || 'us-east-1')
config.namespace = nil # To namespace tables created by Dynamoid from other tables you might have. Set to nil to avoid namespacing.
config.warn_on_scan = true # Output a warning to the logger when you perform a scan rather than a query on a table.
config.read_capacity = 100 # Read capacity for your tables
config.write_capacity = 200 # Write capacity for your tables
config.endpoint = (ENV['DYNAMO_ENDPOINT'] || APP_CONFIG[:dynamo_endpoint]) # [Optional]. If provided, it communicates with the DB listening at the endpoint. This is useful for testing with [Amazon Local DB] (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tools.DynamoDBLocal.html).
end
Make sure you update your ENV variables. Or if you connect directly to AWS instead of Dynamoid gem just follow...
def client
#client ||= Aws::DynamoDB::Client.new(
access_key_id: (ENV['AWS_ACCESS_KEY_ID'] || APP_CONFIG[:aws_access_key_id]),
secret_access_key: (ENV['AWS_SECRET_ACCESS_KEY'] || APP_CONFIG[:aws_secret_access_key]),
region: (ENV['AWS_REGION'] || 'us-east-1'),
endpoint: (ENV['DYNAMO_ENDPOINT'] || APP_CONFIG[:dynamo_endpoint])
)
end
and do a query like this
client.query(
table_name: table_name,
select: 'COUNT',
expression_attribute_values: {
':v1' => index
},
key_condition_expression: 'user_id = :v1'
).count
For more info http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/DynamoDB.html
I am using netaddr gem to validate network IP range. But I unable to find the way validated given subnet mask is valid?
def valid_ip_range(ip, gateway, subnet_mask)
ip_range = NetAddr::CIDR.create("#{gateway} #{subnet_mask}")
valid_ip_range = NetAddr.range(ip_range.first, ip_range.last)
valid_ip_range.include?(ip_ip)
end
For Valid subnet mask
ip_range = NetAddr::CIDR.create('192.168.1.1 255.255.255.0')
=> #<NetAddr::CIDRv4:0x0000000b334720 #address_len=32, #all_f=4294967295, #hostmask=255, #ip=3232235777, #netmask=4294967040, #network=3232235776, #tag={}, #version=4, #wildcard_mask=4294967040>
For Invalid subnet mask, getting following error
ip_range = NetAddr::CIDR.create('192.168.1.1 255.128.128.0')
ip_range = NetAddr::CIDR.create('192.168.1.1 1.1.1.1')
=> NetAddr::ValidationError: 1.1.1.1 contains '1' bits within the host portion of the netmask.
from /ruby-2.1.1#customerservice-mar/gems/netaddr-1.5.1/lib/validation_shortcuts.rb:182:in `block in validate_netmask_str'
ruby ipaddr
require 'ipaddr'
net1 = IPAddr.new("192.168.2.0/24")
net2 = IPAddr.new("192.168.2.100")
net3 = IPAddr.new("192.168.3.0")
p net1.include?(net2) #=> true
p net1.include?(net3) #=> false
I'm using vagrant to deploy a multiple VM environment, for research purposes, and it was great so far. But now i need to pin each docker container to a specific CPU core, but i don't know how to do that using vagrant. I know i can use the "args" clause on the Vagrantfile to pass the "--cpuset" parameter to the docker run command, but i don't know how to use it in a loop, since i'm launching multiple containers and i need to pin each container to a different CPU core (eg. node1 pins to core #0, node2 pins to core #1, etc).
My current Vagrantfile is as follows, without the CPU Pinning thing:
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
# choose how many machines the cluster will contain
N_VMS = 32
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "tknerr/baseimage-ubuntu-14.04"
config.vm.network "private_network", ip: "192.168.121.2"
config.vm.provider "docker" do |v|
v.has_ssh = true
end
hosts_file = []
1.upto(N_VMS) do |i|
config.vm.define vm_name = "node#{i}" do |config|
config.vm.hostname = vm_name
end
end
script = <<-SCRIPT
apt-get -y update
apt-get -y install libcr-dev mpich2 mpich2-doc arp-scan openssh-server nano make
SCRIPT
script.sub! 'N_VMS', N_VMS.to_s
config.vm.provision "shell", inline: script
end
In the end, i was looking in the wrong place. The correct spot to add the "--cpuset-cpus" was in the config.vm.define block.
The code ended being like this:
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
# choose how many machines the cluster will contain
N_VMS = 32
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "tknerr/baseimage-ubuntu-14.04"
config.vm.network "private_network", ip: "192.168.121.2"
config.vm.provider "docker" do |v|
v.has_ssh = true
end
2.upto(N_VMS+1) do |i|
config.vm.define vm_name = "node#{i}" do |config|
# CPU PINNING CONFIG
config.vm.provider "docker" do |docker|
docker.create_args = ['--cpuset-cpus=' + ((i/2)-1).to_s]
end
config.vm.hostname = vm_name
end
end
script = <<-SCRIPT
apt-get -y update
apt-get -y install libcr-dev mpich2 mpich2-doc arp-scan openssh-server nano make
SCRIPT
script.sub! 'N_VMS', N_VMS.to_s
i=1
config.vm.provision "shell", inline: script
end
Suppose you want to config the vagrant vm in the loop, as the vagrantfile is based on the ruby language, so you can involve the development availablty to the vagrantfile, here is an example, you can add your "--cpuset" config in the vm define.
# -*- mode: ruby -*-
# vi: set ft=ruby :
# read vm and chef configurations from JSON files
nodes_config = (JSON.parse(File.read("nodes.json")))['nodes']
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
nodes_config.each do |node|
node_name = node[0] # name of node
node_values = node[1] # content of node
# puts node_name
# puts node_values['box']
config.vm.define node_name do |config|
config.vm.box = node_values['box']
config.vm.hostname = node_name
config.vm.network :private_network, ip: node_values['ip']
config.vm.provider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--memory", node_values['memory']]
vb.customize ["modifyvm", :id, "--name", node_name]
end
end
end
nodes.json to define the vm, you can define your
{
"nodes": {
"jenkins.example.com": {
"info": "jenkins master server",
"box": "../Vgrant-boxes/centos65_virtualbox_50G.box",
"ip": "192.168.35.101",
"ports": [],
"memory": 512
},
"node01.example.com": {
"info": "tomcat app host server",
"box": "../Vgrant-boxes/centos65_virtualbox_50G.box",
"ip": "192.168.35.121",
"ports": [],
"memory": 512
},
"node02.example.com": {
"info": "jboss app host server",
"box": "../Vgrant-boxes/centos65_virtualbox_50G.box",
"ip": "192.168.35.122",
"ports": [],
"memory": 512
},
"node03.example.com": {
"info": "oracle xe server",
"box": "../Vgrant-boxes/centos65_virtualbox_50G.box",
"ip": "192.168.35.123",
"ports": [],
"memory": 512
},
"node04.example.com": {
"info": "artifactory server",
"box": "../Vgrant-boxes/centos65_virtualbox_50G.box",
"ip": "192.168.35.124",
"ports": [],
"memory": 512
}
}
}