bla*_*fci 7 google-cloud-storage google-compute-engine docker google-cloud-platform google-cloud-sdk
我的用例与此问题的其他用例略有不同,因此有一点预先描述:
我在 Google Cloud 上工作并且有一个“dockerized”的 Django 应用程序。部分应用程序依赖于使用 gsutil 将文件移入/移出 Google Storage 存储分区。由于各种原因,我们不想使用 Google Container Engine 来管理我们的容器。相反,我们希望通过启动额外的 Google Compute VM 来水平扩展,这些 VM 将依次运行这个 Docker 容器。与https://cloud.google.com/python/tutorials/bookshelf-on-compute-engine类似,除了我们将使用容器而不是拉取 git 存储库。
VM 将从基本的 Debian 映像构建,并且依赖项(例如 Docker 本身)的启动和安装将使用启动脚本(例如gcloud compute instances create some-instance --metadata-from-file startup-script=/path/to/startup.sh)进行编排。
如果我手动创建一个虚拟机,迅速提升用sudo -s,运行gsutil config -f(这将创建在/root/.boto凭证文件),然后运行我的泊坞窗容器(见下文Dockerfile)与
docker run -v /root/.boto:/root/.boto username/gs gsutil ls gs://my-test-bucket 
那么它的工作原理。但是,这需要我的交互才能创建 boto 文件。
我的问题是:如何将默认服务凭据传递给将在该新 VM 中启动的 Docker 容器?
gsutil 甚至可以在“新鲜”的 Debian VM 上开箱即用,因为它使用所有 VM 加载的默认计算引擎凭据。有没有办法使用这些凭据并将它们传递给 docker 容器?在新的 VM 上第一次调用 gsutil 后,我注意到它创建了 ~/.gsutil 和 ~/.config 文件夹。不幸的是,在 Docker 中安装这两个
docker run -v ~/.config/:/root/.config -v ~/.gsutil:/root/.gsutil username/gs gsutil ls gs://my-test-bucket 
不能解决我的问题。它告诉我:
ServiceException: 401 Anonymous users does not have storage.objects.list access to bucket my-test-bucket.
最小的 gsutil Dockerfile(不是我的):
FROM alpine
#install deps and install gsutil
RUN apk add --update \
    python \
    py-pip \
    py-cffi \
    py-cryptography \
  && pip install --upgrade pip \
  && apk add --virtual build-deps \
    gcc \
    libffi-dev \
    python-dev \
    linux-headers \
    musl-dev \
    openssl-dev \
  && pip install gsutil \
  && apk del build-deps \
  && rm -rf /var/cache/apk/*
CMD ["gsutil"]
补充:一个解决方法:
我已经解决了我的问题,但它非常迂回,所以如果可能的话,我仍然对更简单的方法感兴趣。所有详细信息如下:
首先,说明:我首先在 web 控制台中创建了一个服务帐户。然后我将 JSON 密钥文件(称为凭据.json)保存到存储桶中。在 GCE VM 的启动脚本中,我将该密钥文件复制到本地文件系统 ( gsutil cp gs://<bucket>/credentials.json /gs_credentials/)。然后我启动我的 docker 容器,挂载该本地目录。然后,当 docker 容器启动时,它会运行一个脚本来验证凭据。
以下是一个小型工作示例的文件:
Dockerfile:
FROM alpine
#install deps and install gsutil
RUN apk add --update \
    python \
    py-pip \
    py-cffi \
    py-cryptography \
    bash \
    curl \
  && pip install --upgrade pip \
  && apk add --virtual build-deps \
    gcc \
    libffi-dev \
    python-dev \
    linux-headers \
    musl-dev \
    openssl-dev \
  && pip install gsutil \
  && apk del build-deps \
  && rm -rf /var/cache/apk/*
# install the gcloud SDK- 
# this allows us to use gcloud auth inside the container
RUN curl -sSL https://sdk.cloud.google.com > /tmp/gcl \
      && bash /tmp/gcl --install-dir=~/gcloud --disable-prompts
RUN mkdir /startup
ADD gsutil_docker_startup.sh /startup/gsutil_docker_startup.sh
ADD get_account_name.py /startup/get_account_name.py
ENTRYPOINT ["/startup/gsutil_docker_startup.sh"]
gsutil_docker_startup.sh: 采用单个参数,即 JSON 格式的服务帐户凭据文件的路径。该文件存在是因为主机上的目录已安装在容器中。
#!/bin/bash
CRED_FILE_PATH=$1
mkdir /results
# List the bucket, see that it gives a "ServiceException:401"
gsutil ls gs://<input bucket> > /results/before.txt
# authenticate the credentials- this creates a .boto file:
/root/gcloud/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=$CRED_FILE_PATH
# need to extract the service account which is like:
# <service acct ID>@<google project>.iam.gserviceaccount.com"
SERVICE_ACCOUNT=$(python /startup/get_account_name.py $CRED_FILE_PATH)
# with that service account, we can locate the .boto file:
export BOTO_PATH=/root/.config/gcloud/legacy_credentials/$SERVICE_ACCOUNT/.boto
# List the bucket and copy the file to an output bucket for good measure
gsutil ls gs://<input bucket> > /results/after.txt
gsutil cp /results/*.txt gs://<output bucket>/
get_account_name.py:
import json
import sys
j = json.load(open(sys.argv[1]))
sys.stdout.write(j['client_email'])
然后,GCE 启动脚本(在 VM 启动时自动执行)是:
#!/bin/bash
# <SNIP>
# Install docker, other dependencies
# </SNIP>
# pull docker image
docker pull userName/containerName
# get credential file:
mkdir /cloud_credentials
gsutil cp gs://<bucket>/credentials.json /cloud_credentials/creds.json
# run container
# mount the host machine directory where the credentials were saved.
# Note that the container expects a single arg, 
# which is the path to the credential file IN THE CONTAINER
docker run -v /cloud_credentials:/cloud_credentials \ 
    userName/containerName /cloud_credentials/creds.json
您可以将特定服务帐户分配给您的实例,然后在代码中使用应用程序默认凭据。请在测试前验证这些要点。
身份验证令牌由应用程序默认凭据通过Google 元数据服务器自动检索,该服务器也可从您的实例和 Docker 容器中获取。无需管理任何凭证。
def implicit():
  from google.cloud import storage
  # If you don't specify credentials when constructing the client, the
  # client library will look for credentials in the environment.
  storage_client = storage.Client()
  # Make an authenticated API request
  buckets = list(storage_client.list_buckets())
  print(buckets)
我也很快用 docker 进行了测试,并且工作得很好
yann@test:~$ gsutil cat gs://my-test-bucket/hw.txt
Hello World
yann@test:~$ docker run --rm google/cloud-sdk gsutil cat gs://my-test-bucket/hw.txt
Hello World
| 归档时间: | 
 | 
| 查看次数: | 3329 次 | 
| 最近记录: |