Python 从GCE实例使用时,Google应用程序引擎管理API不工作?

Python 从GCE实例使用时,Google应用程序引擎管理API不工作?,python,google-app-engine,google-cloud-platform,Python,Google App Engine,Google Cloud Platform,我试图通过Python客户端库使用,并使用普通的cURL调用 这在本地机器上运行良好,但在GCE机器上没有这么多 我尝试的cURL命令如下: $ curl -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" https://appengine.googleapis.com/v1beta4/apps/myapp { "name": "apps/myapp", "id": "myapp" } 这是在我的

我试图通过Python客户端库使用,并使用普通的cURL调用

这在本地机器上运行良好,但在GCE机器上没有这么多

我尝试的cURL命令如下:

$ curl -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" https://appengine.googleapis.com/v1beta4/apps/myapp
{
  "name": "apps/myapp",
  "id": "myapp"
}
这是在我的本地机器上成功执行的,其中TOKEN是我个人帐户的oauth2舞蹈的结果

GCE机器上的相同命令:

$ curl -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" https://appengine.googleapis.com/v1beta4/apps/myapp
curl: (7) Failed to connect to appengine.googleapis.com port 443: Connection timed out
无论我使用的是基于oauth2的个人令牌,还是从运行中获得的基于服务帐户的令牌,都会发生这种行为

curl http://metadata/computeMetadata/v1/instance/service-accounts/default/token -H "Metadata-Flavor: Google"
类似地,在尝试使用Python客户端库时

下面是我在Python中所做工作的部分片段:

gae = discovery.build('appengine', 'v1beta4')
method = gae.apps().get(appsId='myapp')
method.execute(http=my_authorized_http_instance)
my\u authorized\u http\u实例
是使用
https://www.googleapis.com/auth/cloud-platform
范围

在本地机器上,这工作正常,我得到一个描述
myapp
的响应

在GCE实例上,执行最后一行需要很长时间,最终引发此异常:

ResponseNotReady                          Traceback (most recent call last)
<ipython-input-9-b5373a41f867> in <module>()
----> 1 meth.execute(http=http)

/usr/local/lib/python2.7/dist-packages/oauth2client/util.pyc in positional_wrapper(*args, **kwargs)
    135         else: # IGNORE
    136           pass
--> 137       return wrapped(*args, **kwargs)
    138     return positional_wrapper
    139

/usr/local/lib/python2.7/dist-packages/googleapiclient/http.pyc in execute(self, http, num_retries)
    720
    721       resp, content = http.request(str(self.uri), method=str(self.method),
--> 722                                    body=self.body, headers=self.headers)
    723       if resp.status < 500:
    724         break

/usr/local/lib/python2.7/dist-packages/oauth2client/util.pyc in positional_wrapper(*args, **kwargs)
    135         else: # IGNORE
    136           pass
--> 137       return wrapped(*args, **kwargs)
    138     return positional_wrapper
    139

/usr/local/lib/python2.7/dist-packages/oauth2client/client.pyc in new_request(uri, method, body, headers, redirections, connection_type)
    549
    550       resp, content = request_orig(uri, method, body, clean_headers(headers),
--> 551                                    redirections, connection_type)
    552
    553       if resp.status in REFRESH_STATUS_CODES:

/usr/local/lib/python2.7/dist-packages/httplib2/__init__.pyc in request(self, uri, method, body, headers, redirections, connection_type)
   1606                     content = ""
   1607                 else:
-> 1608                     (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
   1609         except Exception, e:
   1610             if self.force_exception_to_status_code:

/usr/local/lib/python2.7/dist-packages/httplib2/__init__.pyc in _request(self, conn, host, absolute_uri, request_uri, method, body, headers, redirections, cachekey)
   1348             auth.request(method, request_uri, headers, body)
   1349
-> 1350         (response, content) = self._conn_request(conn, request_uri, method, body, headers)
   1351
   1352         if auth:

/usr/local/lib/python2.7/dist-packages/httplib2/__init__.pyc in _conn_request(self, conn, request_uri, method, body, headers)
   1304                     continue
   1305             try:
-> 1306                 response = conn.getresponse()
   1307             except httplib.BadStatusLine:
   1308                 # If we get a BadStatusLine on the first try then that means

/usr/lib/python2.7/httplib.pyc in getresponse(self, buffering)
   1037         #
   1038         if self.__state != _CS_REQ_SENT or self.__response:
-> 1039             raise ResponseNotReady()
   1040
   1041         args = (self.sock,)

ResponseNotReady:
此外,我想弄清楚服务帐户问题是否出在这里,所以我尝试在GCE实例上以我自己的身份进行授权,而不是使用服务帐户。我也犯了同样的错误

有什么想法吗?我做错什么了吗?

您遇到了托管虚拟机的内部错误,我们正在修复该错误

目前,
appengine.googleapis.com
被映射到虚拟机上的一个内部地址,该地址用于私有虚拟机到appengine的通信,但不会将HTTPS请求转发到公共API。我们正在移动这个内部渠道,以免干扰公共渠道

同时,您可以在计算机上的
/etc/hosts
文件中添加
appengine.googleapis.com
的手动条目,并重新映射端口10001(用于内部通信)以指向内部传输地址,如下所示:

echo '64.233.181.95 appengine.googleapis.com' >> /etc/hosts
sysctl net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp -d 64.18.0.0/20,64.233.160.0/19,66.102.0.0/20,66.249.80.0/20,72.14.192.0/18,74.125.0.0/16,108.177.8.0/21,173.194.0.0/16,207.126.144.0/20,209.85.128.0/17,216.58.192.0/19,216.239.32.0/19 --dport 10001 -j DNAT --to-destination 169.254.169.253:10001
(其中IP地址集源自
\u spf.google.com
记录。)

这仅影响已启用托管VM的项目。我们希望很快(几周)就可以修复


UPD:修复了上面命令中的appengine.googleapis.com域名

我不清楚的两件事:你说的“在GCE实例中”是什么意思?何时部署应用程序?或者,您是否使用从您管理的GCE实例运行的代码构建自己的应用程序?另外,为什么不发送HTTP请求并尝试使用discovery docs?@Patrice 1-我指的是一个从我管理的GCE实例运行的应用程序,我想从该实例与AppEngine管理API进行交互。2-我不知道你所说的“发送HTTP请求”是什么意思-IIUC
gae=discovery.build('appengine','v1beta4')
正在使用discovery文档(Python)。感谢你回答这些:)我只是不确定你是真的指调用代码的GCE,还是在GCE上调用“部署的gae应用程序”。至于发送请求。我在这里用API浏览器中的“apps.get”方法进行了测试,似乎您最终所做的就是请求“get”。你不能自己把那个休息请求发上去吗?(我不知道我是否更清楚)@Patrice不完全确定我是否理解。我尝试了这个“原始”cURL GET
cURL-H“内容类型:application/json”-H“授权:Bearer$TOKEN”https://appengine.googleapis.com/v1beta4/apps/myapp
在本地计算机上在GCE计算机上。它在本地计算机上成功,在GCE计算机上失败。我将更新我的原始问题,从这个测试中获得更多细节。谢谢!尝试了以下解决方法,但appengine.googleapis.com仍然解析为169.254.169.253,而不是64.233.181.95…@Itamar,我修复了此答案中域中的一个拼写错误,只想通知您这可能是它不起作用的原因。
echo '64.233.181.95 appengine.googleapis.com' >> /etc/hosts
sysctl net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp -d 64.18.0.0/20,64.233.160.0/19,66.102.0.0/20,66.249.80.0/20,72.14.192.0/18,74.125.0.0/16,108.177.8.0/21,173.194.0.0/16,207.126.144.0/20,209.85.128.0/17,216.58.192.0/19,216.239.32.0/19 --dport 10001 -j DNAT --to-destination 169.254.169.253:10001