IBM Cloud Object Storage内のコンテンツを静的Webサイトとして公開する


はじめに

IBM Cloud Object Storage(ICOS)に配置した静的コンテンツをWebサイトとして公開する方法です。
ICOSにはWebホスティング機能がない(以下参照)ため、Nginxを前段にたててリバースプロキシとして利用しています。

IBM Cloud Docsより引用 (https://console.bluemix.net/docs/services/cloud-object-storage/iam/public-access.html#static-website-hosting

IBM Cloud Object Storage does not support automatic static website hosting, but it is possible to manually configure a web server and use it to serve publically accessible content hosted in Object Storage. For more information, see this tutorial.

実はこのページ(https://www.ibm.com/blogs/bluemix/2017/03/static-websites-cloud-object-storage-cos/ )にやり方が書いてあるのですが、情報が古くなっていたので今の環境でやってみました。

なお、記事のなかでは"Bluemix Containers"というサービスを使っているのですが、現在はなくなってIBM Cloud Kubernetes Service(IKS)になっていますので、こちらを使います。

前提

  • IBM Cloudのアカウント
    • Kubernetesクラスターを作るためにはクレジットカード登録をしたPAYGアカウントが必要です。
  • IBM Cloud CLI
    • IKSを操作する際に必要となります。
  • s3cmd
  • Docker
  • Kubernetes CLI(kubectl)
    • Nginxコンテナを作成する際に必要です。

ICOSのファイルのパブリック公開

IBM Cloudのカタログ(https://cloud.ibm.com/catalog/services/cloud-object-storage )からサービスを作成します。ライト・プランでOKです。

バケットの作成

サービスが作成できたらバケットを作成します。「回復力」と「ロケーション」はお好きにどうぞ。

Credential情報の生成

「サービス資格情報」から、新規資格情報を追加します。
あとからs3cmdで操作するために必要なので、オプションのところに{"HMAC":true} と記述するのを忘れないようにしてください。
これを記入することでアクセスキーとシークレットキーが生成されます。

資格情報が作成できたので表示してみると、たしかにアクセスキーとシークレットキーが作られています。

s3cmdの設定

ここからはコマンドでの操作です。
s3cmdでICOS上のファイルを扱えるようにするためにまずは~/.s3cfgファイルを修正します。

以下のコマンドを叩くとアクセスキーやシークレットキー、リージョン、エンドポイントなどを入力していきます。

$ s3cmd --configure

以下はサンプルの設定例です。
https://gist.githubusercontent.com/greyhoundforty/a4a9d80a942d22a8a7bf838f7abbcab2/raw/05ad584edee4370f4c252e4f747abb118d0075cb/example.s3cfg

エンドポイントは選択した回復力、ロケーションによって異なりますのでご注意を。
ICOSの詳細画面の「エンドポイント」から確認できます。

$ s3cmd lsとか叩いて作成したバケット一覧が表示されればOKです。

新規オブジェクトをアップロードしてPublic公開する

適切なディレクトリで以下のコマンドを叩いてください。ファイル名は必要に応じて変更します。
後半の部分はs3://バケット名/オブジェクト名です。

$ s3cmd --acl-public put index.html s3://MyBucket/index.html

upload: 'index.html' -> 's3://MyBucket/index.html'  [1 of 1]
 508 of 508   100% in    1s   323.45 B/s  done
Public URL of the object is: http://s3.us-south.objectstorage.softlayer.net/MyBucket/index.html

これでICOSへのアップロード&Public公開ができました。最後に書いてあるPublic URLにアクセスすれば
ファイルを見ることができるようになっています(記事内のアドレスはダミーです)。
https://s3.us-south.objectstorage.softlayer.net/MyBucket/index.html

ちなみに、すでにアップロード済みのオブジェクトをPublic公開に変更する場合は以下ようなコマンドになります。

s3cmd setacl --acl-public s3://MyBucket/index.html

Nginxをリバースプロキシとして構成する

Nginxはコンテナで作り、それをIKS上で動かします。

Nginxのコンテナを作成

まずはDockerfileを書きます。

FROM nginx:latest
COPY ./default.conf /etc/nginx/conf.d/
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]

次にdefault.confファイルを以下のように作ります。

default.conf
server {
listen 80 default_server;

add_header Strict-Transport-Security "max-age=31557600; includeSubDomains";
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Xss-Protection "1";

location / {
set $s3_bucket 's3.us-south.objectstorage.softlayer.net/MyBucket/index.html';

index index.html;

proxy_http_version 1.1;
proxy_set_header Host $s3_bucket;
proxy_set_header Authorization ”;
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header Set-Cookie;
proxy_ignore_headers "Set-Cookie";
proxy_buffering off;
proxy_intercept_errors on;
resolver 8.8.8.8 valid=300s;
resolver_timeout 10s;

proxy_pass https://$s3_bucket;
}
}

2つのファイルが完成したらdocker buildします。

$ docker build --tag XXXXXX/my-nginx .

ビルドできたらDocker Hubへプッシュ

$ docker push XXXXXX/my-nginx

IKS上にコンテナをデプロイ

サクッと公開したいだけなのでyamlファイルは書かずにコマンドで済ませちゃいます。
まずはDeploymentを作成します。

$ kubectl run nginx-deployment --image=XXXXXX/my-nginx

次に、Serviceのエクスポートです。
元記事ではカスタムドメインを持ち込んでいるので、本来であればIngressでの公開・・といきたいところなのですが諸事情によりNodePortでの公開となります。

$ kubectl expose deployment/nginx-deployment --type=NodePort --port=80 --name=nginx-service --target-port=80

動作確認

IKSのPublic IPとNodeportで公開されているポートを確認してアクセスしてみます。

# クラスターのPublic IPの確認
$ ibmcloud ks workers クラスタ名

# NodePortのポート確認
$ kubectl get svc

出てきたhttp://<IP_address>:<NodePort>にアクセスすれば、Nginx経由でICOSのファイルが公開されていることが確認できると思います。