Go言語の初心者として今回は、Go言語のアプリを IBM Cloud コンテナサービス すなわち Kubernetes(以下 k8s) のクラスタにデプロイするまでを考えます。順番としては、DockerコンテナをビルドするためのDockerファイルの開発、そして、ローカルのDocker環境でのテスト、それから、k8sへデプロイするためコンテナレジストリへの登録、そして、k8sへのデプロイの流れになります。
Cloud Foundry の手軽さからすると、k8s へのデプロイは面倒な感じがしますね。 Dockerコンテナをそのままデプロイできる処は素晴らしいですが、もっと、自動化したいものですが、今期は手作業で進めます。
Go言語アプリは、以下の3つのリポジトリから構成されるもので、一番目のリポジトリから、2番目を依存パッケージとして、3番目は2番目の依存パッケージとして構成しています。
- ウェブコンテンツ、各種定義ファイル https://github.com/takara9/go_webpages
- Go言語で書いたシンプルなWebサーバー https://github.com/takara9/go_webserver2
- Go言語の共通モジュール https://github.com/takara9/go_util
上記の1番目のリポジトリの内容は、参考資料の3を参照してください。
手打ちでDockerコンテナをビルドして、Dockerfileに必要な材料を確認
その3で作成した リポジトリ https://github.com/takara9/go_webpages から、Go言語で書いたウェブサーバーのコンテナをビルドして、動作させるまでの、作業手順を試行錯誤で作ったものが、以下になります。 パッケージ・マネージャーのgodep restore
で前提パッケージを集めて、go install
でビルドして、実行という流れです。
$ docker run -it golang bash
root@5d68e424048f:/go# echo $GOPATH
/go
rm -fr go
cd /
git clone https://github.com/takara9/go_webpages --recursive go
cd /go
go get github.com/tools/godep
godep restore
go install github.com/takara9/go_webserver2
bin/go_webserver2
コンテナ内でサーバーgo_webserver2を起動
手打ちで実行した go_webserver2が正しく動作しているか確認します。 ビルドでは、対話モードでコンテナに入って作業していたので、上記の稼働中のコンテナに別のターミナルから入って、curlコマンドでアクセスしてテストします。
以下は、上記と同じコンテナに入った処です。 go_webserver2が動作しているのが確認できます。
$ docker exec -it 4707e89a7800 bash
root@4707e89a7800:/go# ps -ax
PID TTY STAT TIME COMMAND
1 pts/0 Ss 0:00 bash
509 pts/0 Sl+ 0:00 bin/go_webserver2
512 pts/1 Ss 0:00 bash
516 pts/1 R+ 0:00 ps -ax
同じコンテナに入ってcurlのアクセス・テスト
curlの実行結果です。 確かにHTMLコンテンツを送出している事が確認したできました。
root@4707e89a7800:/go# curl http://localhost:4040/
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Go言語で作ったウェブサーバー</title>
<meta charset="utf-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<H1>質問#1</H1>
<p>歌詞などで表現される「時計仕掛けの夜」とはなんだろう?</p>
<br>
<img src="gopher.png">
<br>
<a href="test_doc_1.html">答えページへ進む</a>
</body>
</html>
コンテナをビルドして、ローカルでテスト
Dockerfileの作成
上記の手打ちの結果をもとに、Dockerfileを作成したのが、以下のファイルです。
FROM golang:1.9.2
RUN rm -fr $GOPATH
RUN git clone https://github.com/takara9/go_webpages --recursive $GOPATH
WORKDIR $GOPATH
RUN go get github.com/tools/godep
RUN godep restore
RUN go install github.com/takara9/go_webserver2
EXPOSE 4040
ENTRYPOINT ["bin/go_webserver2"]
ビルドの実行
上記のDockerfileを利用してローカルのMacの環境で、コンテナをビルドして、テストします。
vagrant@vagrant-ubuntu-trusty-64:~/go/go_webpages$ docker build -t go_webserver .
Sending build context to Docker daemon 423.9kB
Step 1/9 : FROM golang:1.9.2
---> 138bd936fa29
Step 2/9 : RUN rm -fr $GOPATH
---> Running in 68a725444541
---> fb59c95a1e5f
Removing intermediate container 68a725444541
Step 3/9 : RUN git clone https://github.com/takara9/go_webpages --recursive $GOPATH
---> Running in 2b5f79923ce9
Cloning into '/go'...
Submodule 'vendor/github.com/takara9/go_util' (https://github.com/takara9/go_util.git) registered for path 'vendor/github.com/takara9/go_util'
Submodule 'vendor/github.com/takara9/go_webserver2' (https://github.com/takara9/go_webserver2.git) registered for path 'vendor/github.com/takara9/go_webserver2'
Cloning into '/go/vendor/github.com/takara9/go_util'...
Cloning into '/go/vendor/github.com/takara9/go_webserver2'...
Submodule path 'vendor/github.com/takara9/go_util': checked out '38ff0221e206b57cd7ea242e4f1238fb8f613b8a'
Submodule path 'vendor/github.com/takara9/go_webserver2': checked out '25d39c2700995e71dbb9a3b9c80891cec437ffd5'
---> 756ad9a01728
Removing intermediate container 2b5f79923ce9
Step 4/9 : WORKDIR $GOPATH
---> eccea02c8da2
Removing intermediate container f1d8e8634a95
Step 5/9 : RUN go get github.com/tools/godep
---> Running in 0dc09366ed94
---> b1d4f2e4c65d
Removing intermediate container 0dc09366ed94
Step 6/9 : RUN godep restore
---> Running in 4f048faa37a3
godep: [WARNING]: godep should only be used inside a valid go package directory and
godep: [WARNING]: may not function correctly. You are probably outside of your $GOPATH.
godep: [WARNING]: Current Directory: /go
godep: [WARNING]: $GOPATH: /go
---> 29ee74bb965b
Removing intermediate container 4f048faa37a3
Step 7/9 : RUN go install github.com/takara9/go_webserver2
---> Running in dd5fbd7202ef
---> 4ad3472126d3
Removing intermediate container dd5fbd7202ef
Step 8/9 : EXPOSE 4040
---> Running in d556fe610c0c
---> 4cf9d6904ea9
Removing intermediate container d556fe610c0c
Step 9/9 : ENTRYPOINT bin/go_webserver2
---> Running in 48123c88fc70
---> a9b6339a9a56
Removing intermediate container 48123c88fc70
Successfully built a9b6339a9a56
Successfully tagged go_webserver:latest
コンテナ・イメージができていることを確認
vagrant@vagrant-ubuntu-trusty-64:~/go/go_webpages$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
go_webserver latest a9b6339a9a56 7 seconds ago 751MB
コンテナのテスト
コンテナをデーモンとして起動
vagrant@vagrant-ubuntu-trusty-64:~/go/go_webpages$ docker run -d -p 8080:4040 go_webserver
568cdb58537aa9947821ab2ca2faa3ea4cb76101481f44a2d259644bf456c7cc
curlでのアクセステストで、HTMLコンテンツの応答がきたので、テスト完了です。
vagrant@vagrant-ubuntu-trusty-64:~/go/go_webpages$ curl http://localhost:8080/
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Go言語で作ったウェブサーバー</title>
<meta charset="utf-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<H1>質問#1</H1>
<p>歌詞などで表現される「時計仕掛けの夜」とはなんだろう?</p>
<br>
<img src="gopher.png">
<br>
<a href="test_doc_1.html">答えページへ進む</a>
k8sのコンテナ・レジストリへ登録
コンテナをK8sクラスタへデプロイするために、IBM Cloud レジストリサービスへコンテナを登録します。
東京DCのk8sクラスタを利用するために、ap-southのレジストリを利用します。 ネームスペースは既に作成しておいた takara
を利用します。
ローカルのコンテナ・レジストリにタグを付けて、リモート・レジストリへプッシュする流れです。
$ bx cr region-set ap-south
$ bx cr login
$ bx cr namespace-list
<中略>
Namespace
takara
$ docker tag go_webserver:latest registry.au-syd.bluemix.net/takara/go_webserver:v1
$ docker push registry.au-syd.bluemix.net/takara/go_webserver:v1
リモート・レジストリ、すなわち、IBM Cloudのレジストリ・サービスに登録された事がわかります。 このレジストリは、プライベートなので、失敗した場合は、bx cr login
を確認してください。
$ bx cr images
<中略>
NAMESPACE TAG DIGEST CREATED SIZE VULNERABILITY STATUS
registry.au-syd.bluemix.net/takara/go_webserver takara v1 ecfd885a3874 24 minutes ago 279 MB Vulnerable
これで 東京DC の k8s へデプロイする準備が整いました。
Kubernetesへのデプロイと公開
k8sへデプロイして、サービスとして内部公開、さらにIngressサービスで外部へ公開するために、3つのYAMLファイルを準備します。
次は、コンテナをポッドとして、デプロイするためのYAMLです。 imageのフィールドに、先に登録したリポジトリ名をセットします。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: go-web-deploy
spec:
replicas: 3
template:
metadata:
labels:
app: go-web
spec:
containers:
- name: go-web
image: registry.au-syd.bluemix.net/takara/go_webserver:v1
ports:
- containerPort: 4040
次は、デプロイしたポッドが、k8sクラスタの他からアクセスできる様にするサービスを定義するものです。
これにより、ポッドのクラスタの代表アドレスが取得され、k8sのDNSサービスに登録されます。 これによって、Ingressから接続できる様になります。
apiVersion: v1
kind: Service
metadata:
name: go-web-svc
spec:
type: ClusterIP
selector:
app: go-web
ports:
- protocol: TCP
port: 8080
targetPort: 4040
次は、パブリック・ネットワークであるインターネットから HTTPでアクセスするために、設定する Igressサービスの定義です。
go-web-svcの8080ポートをプロキシーして、外部へ公開します。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: go-web-ingress
spec:
tls:
- hosts:
- mycluster3.jp-tok.containers.mybluemix.net
secretName: mycluster3
rules:
- host: mycluster3.jp-tok.containers.mybluemix.net
http:
paths:
- path: /
backend:
serviceName: go-web-svc
servicePort: 8080
次のコマンドで、k8sクラスタへのデプロイを実行します。 このコマンドが実行できる様になるまでに、bx login、k8sクラスタのセットアップなどの作業がありますが、ここでは省略しています。ごめんなさい。
kubectl apply -f k8s_deploy.yml
kubectl apply -f k8s_svc.yml
kubectl apply -f k8s_ingress.yml
デプロイが成功したら、ブラウザからアクセスできる様になります。
まとめ
Go言語で開発したアプリをk8sクラスタで公開するまでの作業内容を確認してみました。 流れをまとめると、以下の様になると思います。
- Go言語で開発したサービスをコンテナ化
- Dockerfileを開発して、ビルドとローカルでのテスト
- k8sクラスタ環境のセットアップ(今回は省略)
- コンテナのレジストリサービスへ登録
- k8sのクラスタへデプロイするためのYAMLファイル作成
- kubectrlでデプロイ
Go言語だからといって、特別な事は無いのですが、GitHubとgodepの使い方が、重要な事が良く判りました。
参考資料
- IBM Cloud を利用して Go言語のアプリ開発入門(その1) https://qiita.com/MahoTakara/items/70572f3f214f24ee452d
- IBM Cloud を利用した Go言語のアプリ開発入門(その2) https://qiita.com/MahoTakara/items/76d5d7905d07c9452d06
- IBM Cloud を利用した Go言語のアプリ開発入門(その3) https://qiita.com/MahoTakara/items/20dcb775f97eaf4a73dd
- 今さらだけど、Go言語に入門するための情報源 https://qiita.com/MahoTakara/items/10fede35c03db1e3b849
- Ingress のアノテーション IBM Cloud Docs https://console.bluemix.net/docs/containers/cs_annotations.html#service-rate-limit
- Docker-docs-ja http://docs.docker.jp/engine/toc.html