From an SEO perspective I'm not sure its a great idea, I have little experience optimizing for SEO. But....
If the title of your Node is the cityname. I would simply make its url path pattern in Pathauto as city/[node:title].
That takes care of the url /city/cityname.
Then you can simply use the Tagging taxonomy installed by default to tag the city with relevant keywords.
Then install the 3rd party contributed module: view_mode_page
It allows you to define alternate pattern(s) to get to a piece of Node content.
Then use its API to create the alternate urls based on the tags.
Something like this example code in a custom module (untested, as I dont have your exact setup):
/**
* Implementation of hook_view_mode_page_get_patterns() from module
* view_mode_page.
*
* This lets me define additional node urls (per NID) with a custom
* view mode.
*
* Creating a custom view mode, and using Display Suite for example could let
* you customize these pages so they're slightly more unique in content layout
* and values.
*/
function MYMODULE_view_mode_page_get_patterns($results, $content_type, $view_mode) {
$results = array();
$defaults = array('content_type' => 'CITY_CONTENT_TYPE', 'view_mode' => 'full' /* or a custom view mode */, 'show_title' => 0, 'title' => '');
// Load the terms for keyword vocabulary by its vocabulary name.
$keyword_terms = taxonomy_get_tree(taxonomy_vocabulary_machine_name_load('city_keywords')->vid);
// Loop through the Term objects and build the sub-url using the nodes pathauto alias denoted by %.
foreach ($keyword_terms as $pos => $Term) {
$results[$pos] = (Object) array_merge($defaults, array('url_pattern' => '%/'.$Term->name));
}
return $results;
}
If every city is to have different keywords, this may not work. Or you may have to load all the city nodes and iterate through them to get the correct paths and attached keyword terms. This is just taking a generic keywords list and building additional urls for each city.