When Anya and I were harvesting corn today, we found a butterfly on the corn stalks. It seemed like it was drying its wings – slowly flapping as it basked in the sun.
MongoDB: Changing Host in Replica Set
When we get replacement servers at work, they frequently build a new server with a temporary name and IP address with the plan of swapping the host name and IP with the decommed server. So my Server123 gets turned down, Server123-Temp gets renamed to Server123, and the IP from the old server is configured on the replacement. Everything is operating exactly as it was before even if the direct host name or IP address were used — great for not needing to update firewall rules and vpn profiles, but I encountered a bit of a problem with the MongoDB cluster.
When I initiated the replica set, I did not have to specify a host name. It pulled the host name from the system — which happily provided that temporary name that doesn’t really exist (it’s not in DNS). Which was fine — I could add the temporary name to /etc/hosts along with the future name that I’ve remapped to the current IP so my “new” VMs all talk to each other and the old servers don’t get mucked up.
But, eventually, I’d like the replica set to have the right names. Had I known about this ahead of time, I’d simply have changed the host name value on the box to be the permanent name, initialized the replica set, and returned the temporary name to the box. But I didn’t, and I didn’t really want to start from 0 with the database I’d restored. Luckily, it turns out there’s a process for re-creating the replica set without destroying the data.
First, edit the mongo.conf file and comment out the replica set block. Restart each server with the new config. Then delete the “local” database from each MongoDB server using mongo local --eval "db.dropDatabase()"
Uncomment the replica set block in mongo.conf and restart MongoDB again — initialize the replica set again (make sure the server “knows” it’s proper name first!)
Redis Continually Receiving SIGTERM
I brought up a redis cluster — three servers which all logged basically nothing apart from the fact they were about to shut down. The service status showed as “Activating” — never started — and the server wasn’t doing anything useful.
The redis log reads:
2920940:signal-handler (1694019281) Received SIGTERM scheduling shutdown... 2921151:signal-handler (1694019374) Received SIGTERM scheduling shutdown... 2921518:signal-handler (1694019468) Received SIGTERM scheduling shutdown... 2921726:signal-handler (1694019561) Received SIGTERM scheduling shutdown... 2922133:signal-handler (1694019655) Received SIGTERM scheduling shutdown... 2922410:signal-handler (1694019748) Received SIGTERM scheduling shutdown... 2923173:signal-handler (1694019842) Received SIGTERM scheduling shutdown... 2923537:signal-handler (1694019935) Received SIGTERM scheduling shutdown... 2923747:signal-handler (1694020029) Received SIGTERM scheduling shutdown... 2924110:signal-handler (1694020122) Received SIGTERM scheduling shutdown... 2924319:signal-handler (1694020216) Received SIGTERM scheduling shutdown... 2924687:signal-handler (1694020309) Received SIGTERM scheduling shutdown... 2924900:signal-handler (1694020403) Received SIGTERM scheduling shutdown... 2925266:signal-handler (1694020496) Received SIGTERM scheduling shutdown... 2925467:signal-handler (1694020590) Received SIGTERM scheduling shutdown...
Turns out this is a hazard of copy/pasting a unit file from an older server — evidently redis cannot use a service type of “Forking” with systemd. To resolve the issue, edit /etc/systemd/system/redis.service
and updating the type to “simple”. Use systemctl daemon-reload
and then systemctl restart redis
to launch redis with the new config … voila, I’ve got a cluster of three servers that are started and communicating.
MongoDB: Increasing Log Level
We had a problem with an application accessing our MongoDB cluster, and the log files didn’t provide much useful information. I could see the client connect and disconnect … but nothing in between. I discovered that the default logging level is very low. Good for disk utilization and I/O, but not great for troubleshooting.
db.runCommand({getParameter: 1, logLevel: 1}) # Get the current logging level db.setLogLevel(3) # Fairly robust logging db.setLogLevel(5) # don't try this is prod huge stream of text super logging db.setLogLevel(0) # and set logging back to a low level once you are done troubleshooting
You can also increase the log level for individual components of MongoDB to minimize logging I/O:
db.setLogLevel(2, "accessControl" )
Black Walnuts!
Corn and Beans
Smoking Pork Roasts
Tableau: Workbooks and Views Created or Modified By a Specific Individual
I had a manager looking to locate a ‘something in Tableau’ that was created by a specific individual — in this case, it was a terminated employee so “just ask the person” was not a viable solution. I put together a query to list all workbooks owned by or modified by an individual:
SELECT w.id, w.name, w.description, w.owner_id, w.modified_by_user_id, owner_system_users.email AS owner_email, modified_system_users.email AS modifier_email
FROM public.workbooks AS w
LEFT OUTER JOIN public.users AS owner_users on w.owner_id = owner_users.id
LEFT OUTER JOIN public.users AS modified_users ON w.owner_id = modified_users.id
LEFT OUTER JOIN public.system_users AS owner_system_users ON owner_system_users.id = owner_users.system_user_id
LEFT OUTER JOIN public.system_users AS modified_system_users ON modified_system_users.id = modified_users.system_user_id
WHERE owner_system_users.name = 'UserLogonID';
-- WHERE owner_system_users.email LIKE '%Smith%' OR modified_system_users.email = '%Smith%'
;
As well as a query to identify all views owned by an individual:
SELECT views.*, owner_system_users.email AS owner_email
FROM public.views
LEFT OUTER JOIN public.users AS owner_users on views.owner_id = owner_users.id
LEFT OUTER JOIN public.system_users AS owner_system_users ON owner_system_users.id = owner_users.system_user_id
WHERE owner_system_users.name = 'UserLogonID';
-- WHERE owner_system_users.email LIKE '%Smith%' OR modified_system_users.email = '%Smith%'
;
The email address based search is most reasonable — our email addresses are algorithmically based on our names, so we always know what the address would have been. Many contractors, however, don’t have Office 365 licenses or mailboxes … so I have to fall back to finding their logon ID in those cases.
MongoDB: Setting Up a Replica Set
On one server create a key file. Copy this key file to all other servers that will participate in the replica set
mkdir -p /opt/mongodb/keys/ openssl rand -base64 756 > /opt/mongodb/keys/$(date '+%Y-%m-%d').key chmod 400 /opt/mongodb/keys/$(date '+%Y-%m-%d').key chown -R mongodb:mongodb /opt/mongodb/keys/$(date '+%Y-%m-%d').key
On each server, edit /etc/mongo.conf and add the keyfile to the security section and define a replica set
security: authorization: enabled keyFile: /etc/mongodb/keys/mongo-key #replication: replication: replSetName: "myReplicaSet"
Restart MongoDB on each node.
On one server, use mongosh to enter the MongDB shell.
rs.initiate( { _id: "myReplicaSet", members: [ { _id: 0, host: "mongohost1.example.net" }, { _id: 1, host: "mongohost2.example.net" }, { _id: 2, host: "mongohost3.example.net" } ] })
Use rs.status() to view the status of the replica set. If it is stuck in STARTING … check connectivity. If the port is open, I ran into a snag with some replacement servers. They’ve got temporary hostnames. But you cannot add a host on itself — it ignores that you typed mongohost1.example.net … and it takes it’s hostname
value. And then sends that value to the other servers in the replica set. If you cannot change the hostname to match what you want, there is a process to change the hostname in a replicaset.
MongoDB: Where is my shell?!?
We are upgrading servers from really old MongoDB (4.2.15) to much new MongoDB (6.something). I am used to getting into the MongoDB shell using:
mongoserver:~ # mongo -u $STRMONGOUSER -p $STRMONGOPASS
MongoDB shell version v4.2.15
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("5658a72f-fea0-4316-aa97-4b0c0ffab7ff") }
MongoDB server version: 4.2.15
Except the new server says there’s no such file. And there isn’t. A bit of research later, I learn that the shell is now called mongosh … which is a more reasonable name. It works the same way: mongosh -u $STRMONGOUSER -p $STRMONGOPASS
gets me there, and all of the commands I know work.