"keystone token-get"は成功し、"openstack token issue"は成功しなかった話

"keystone token-get" では token を取得出来るのに、"openstack token issue" では token を取得出来なかった。

他にも、"swift list" は成功するのに、"neutron net-list" は成功しないなどの問題が発生。各サービスの publicURL はグローバル側からアクセス出来るように設定しているはず。。

結論

keystone.conf の "public_endpoint" という項目に、プライベート側の IP アドレスが設定されていた。そこでこの項目をコメントアウトすると無事コマンドが通るようになった。

経緯

OpenStack の各サービスのエンドポイントを

publicURL internalURL adminURL
グローバルIP(192.168.11.XX/24) プライベートIP(10.0.0.0/8) プライベートIP(10.0.0.0/8)

みたいな感じにして、rc ファイルを以下のようにする。

export OS_AUTH_URL=<keystone の publicURL>
export OS_USERNAME=hoge
export OS_PASSWORD=hogehoge

この設定で以下のコマンドを打つと、

$ openstack token issue
ERROR: openstack Unable to establish connection to http://10.0.0.1:5000/v2.0/tokens

keystone の internalURL と adminURL に設定したプライベートIPアドレスに token を取りに行ってエラーになる。

--debug をつけて詳細を見てみる。

DEBUG: keystoneclient.session REQ: curl -g -i -X GET http://192.168.11.100:5000/v2.0/ -H "Accept: application/json" -H "User-Agent: python-openstackclient"
INFO: requests.packages.urllib3.connectionpool Starting new HTTP connection (1): 192.168.11.100
DEBUG: requests.packages.urllib3.connectionpool "GET /v2.0/ HTTP/1.1" 200 334
DEBUG: keystoneclient.session RESP: [200] content-length: 334 vary: X-Auth-Token server: Apache/2.4.6 (CentOS) connection: close date: Thu, 30 Jul 2015 14:42:53 GMT content-type: application/json x-openstack-request-id: req-2d1208c2-e676-4f46-86f5-bb5c240f555e
RESP BODY: {"version": {"status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}], "id": "v2.0", "links": [{"href": "http://10.0.0.1:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/", "type": "text/html", "rel": "describedby"}]}}

DEBUG: keystoneclient.auth.identity.v2 Making authentication request to http://10.0.0.1:5000/v2.0/tokens
INFO: requests.packages.urllib3.connectionpool Starting new HTTP connection (1): 10.0.0.1

このような感じで、一回グローバルIP(今回の環境では192.168.11.100)の'/v2.0/'に GET リクエストを送り、その後プライベートIP(今回の環境では192.168.11.100)の '/v2.0/tokens' に POST リクエストを送ってしまっている。

そして、ここで不思議なのはこの環境のまま "keystone token-get" コマンドだと以下のようにトークンを発行出来るのだ。

$ keystone --debug token-get
/usr/local/lib/python2.7/site-packages/keystoneclient/shell.py:64: DeprecationWarning: The keystone CLI is deprecated in favor of python-openstackclient. For a Python library, continue using python-keystoneclient.
  'python-keystoneclient.', DeprecationWarning)
  DEBUG:keystoneclient.auth.identity.v2:Making authentication request to http://192.168.11.100:5000/v2.0/tokens
  INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): 192.168.11.100
  DEBUG:requests.packages.urllib3.connectionpool:"POST /v2.0/tokens HTTP/1.1" 200 3842
  +-----------+----------------------------------+
  |  Property |              Value               |
  +-----------+----------------------------------+
  |  expires  |       2015-07-30T15:47:18Z       |
  |     id    | faf5683318b24fe7ae97446e675fe720 |
  | tenant_id | 2a2dbd7af00b4edfabd60d86c6731de7 |
  |  user_id  | f631ea7e61b64f82ae76358d19f76c84 |
  +-----------+----------------------------------+

しっかりとグローバルIP側に接続しに行っている。

ここで気になるのは、"openstack token issue" の時の

RESP BODY: {"version": {"status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}], "id": "v2.0", "links": [{"href": "http://10.0.0.1:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/", "type": "text/html", "rel": "describedby"}]}}

この部分。"links" の 一個目の要素の "href" にプライベート側のIPアドレスが入っている。"openstack token issue" の時は、この部分を参照してプライベート側にアクセスしにいってるのではないか。そんな仮説を立てて、この部分を変更できる手段はないかと探してみると、"keystone.conf" に "public_endpoint" という設定項目があることを発見。

# The base public endpoint URL for Keystone that is advertised
# to clients (NOTE: this does NOT affect how Keystone listens
# for connections). Defaults to the base host URL of the
# request. E.g. a request to http://server:5000/v2.0/users
# will default to http://server:5000. You should only need to
# set this value if the base URL contains a path (e.g.
# /prefix/v2.0) or the endpoint should be found on a different
# server. (string value)
#public_endpoint=<None>

実際の"keystone.conf" のこの設定項目を見てみると以下の記述を発見。

pulic_endpoint=http://10.0.0.1:5000/v2.0

この項目を無効にするとデフォルトではリクエストの"Host"ヘッダを見て、public_endpoint を決定するということなので、コメントアウトしてみると、無事 "openstack token issue" が成功しました。

感想

IP 直指定では無くて、ドメイン指定して、グローバルとプライベートそれぞれで名前解決したほうが簡単っぽい。今度"keystoneclient"ライブラリのコードを見てみます。