
 
こんにちは、mabuiです。
今回はDocker HubにGoでHello worldを出力するコンテナイメージをアップロード、それを元にKubernetes(以下k8s)の基本的な機能を使ってイメージを起動していきます。
Dockerでの起動、k8sでの起動と順を追って解説するので、k8sの基本的な使い方が理解できるはずです。
 
Goコンテナの準備
まずはアップロード用のGoプログラムを用意します。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 作業ディレクトリ作成 mkdir template cd template # ルートディレクトリでmoduleの初期化をする。 go mod init github.com/mabuix/template # ファイル作成 touch Dockerfile touch main.go tree . ├── Dockerfile ├── go.mod └── main.go | 
main.go
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package main import (     "fmt"     "log"     "net/http" ) func handler(w http.ResponseWriter, r *http.Request) {     fmt.Fprintln(w, "Hello World!") } func main() {     http.HandleFunc("/", handler)     log.Fatal(http.ListenAndServe(":8888", nil)) } | 
go runで起動するとポート8888でhttpリクエストを待ち受けてHello World!を出力するシンプルなコードです。
 
Dockerfile
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | FROM golang:1.14-alpine AS build # Goコンテナのマルチステージビルドを実行 WORKDIR /src/ COPY main.go go.* /src/ # templateバイナリを作成 RUN CGO_ENABLED=0 go build -o /bin/template # スクラッチイメージ(空のコンテナイメージ)を用意 FROM scratch # スクラッチイメージにtemplateバイナリをコピー COPY --from=build /bin/template /bin/template # templateバイナリの実行(exec) ENTRYPOINT ["/bin/template"] | 
イメージ作成用のファイルです。最終的に空のコンテナイメージにGoのバイナリファイルを乗せることで、Goランタイムをコンテナから省いて軽量化しています。
 
ローカルでイメージをビルドして起動
| 1 2 3 4 5 6 7 | # imageにtemplateと名付けてビルド docker image build -t template . # イメージ名指定で実行 # ローカルマシンのポート9999をコンテナのプライベートポート8888に転送している docker container run -p 9999:8888 template | 
http://localhost:9999/ アクセスでハロワが表示されるはずです。
コンテナのポートには直接アクセスできないので指定したローカルマシンのポートにアクセスします。
 
Docker Hubにイメージアップロード、実行
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # docker hubにログイン % docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: mabui Password:  Login Succeeded # ローカルイメージの命名 docker image tag template mabui/template # ローカルイメージをDocker Hubレジストリにプッシュ docker image push mabui/template # Docker Hub上のイメージを実行 docker container run -p 9999:8888 mabui/template | 
※Docker Hubへの登録が必要です。
上記でDocker Hub上のリモートリポジトリにアップされたイメージをローカルと同じように実行できます。
 
Kubernetesからリモートイメージ実行
ここからk8sを使っていきます!
k8sの実行環境はDocker Desktopを利用しています。
| 1 2 3 4 5 6 | # KubernetesからDocker Hub上のイメージを実行 kubectl run template --image=mabui/template --port=8888 --labels app=template # ローカルマシンのポート9999をコンテナのプライベートポート8888に転送 kubectl port-forward deploy/template 9999:8888 | 
前章でアップしたイメージをk8sのコマンドから実行しています。
挙動的には同じですが、Podが起動しているのが確認できます。
Podはk8sのオブジェクトで、一つ以上のコンテナのグループです。
| 1 2 3 | kubectl get pods --selector app=template                                                                                                                      NAME                       READY   STATUS    RESTARTS   AGE template-c6f5f96d9-7bjtx   1/1     Running   0          18s | 
| 1 2 | kubectl delete pods -—selector app=template | 
Podは上記コマンドで削除できますが、次章で紹介するDeploymentで管理されているためすぐに復活します。
下記コマンドでDeploymentごとシャットダウンできます。
| 1 2 | kubectl delete all --selector app=template | 
Deploymentテンプレートの使用
k8sではマニュフェストと呼ばれる設定ファイルを記述して、コマンド実行時に読み込ませることができます。
| 1 2 | kubectl run template --image=mabui/template --port=8888 --labels app=template | 
先ほどイメージを実行したコマンドにはイメージ、ポート、ラベルの指定がされていますが、これらをDeploymentマニュフェストに移していきます。
 
Deployment はk8sでPodを管理する機能です。
DeploymentにPodの状態を設定することで、Podが異常終了した時に立ち上げ直したり、自動管理してくれます。
 
mkdir k8sでディレクトリを作成して、template/k8s/deployment.yamlを作成
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | apiVersion: apps/v1 kind: Deployment metadata:   name: template   labels:     app: template spec:   replicas: 1   selector:     matchLabels:       app: template   template:     metadata:       labels:         app: template     spec:       containers:       - name: template         image: mabui/template         ports:         - containerPort: 8888 | 
少し長いですが、ほどんどボイラープレートです。
containers:にイメージの名前とポートを指定しています。
 
マニュフェストを使用するにはkubectl applyを実行します。
| 1 2 3 4 5 6 7 8 | kubectl apply -f k8s/deployment.yaml deployment.apps/template created # Podの起動確認 kubectl get pods --selector app=template  NAME READY STATUS RESTARTS AGE template-c6f5f96d9-9vz95 1/1 Running 0 11s | 
これでDeploymentを起動して、kubectl runと同じようにPodを起動できました。
 
Serviceテンプレートの使用
Pod、Deploymentに続きk8sの基本的な機能としてServiceがあり、これを使うことでPodとの通信設定を行えます。
 
| 1 2 | kubectl port-forward deploy/template 9999:8888 | 
先ほどイメージ実行時に上記コマンドでローカルからPodに直接ポート転送していましたが、Podとの間にServiceを挟むことができます。
Serviceのエンドポイントに対して通信することで、紐づけられたPodのグループに通信でき、Webプロキシやロードバランサのような役割を果たします。
 
こちらもDeploymentと同じようにServiceマニュフェストを作成します。
 
template/k8s/service.yaml
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | apiVersion: v1 kind: Service metadata:   name: template   labels:     app: template spec:   ports:   - port: 8888     protocol: TCP     targetPort: 8888   selector:     app: template   type: ClusterIP | 
portsのportとtargetPortで、ServiceのポートとPodのプライベートポートを繋いでいます。
type: ClusterIPだと、Serviceはクラスター内からのみアクセス可能になります(デフォルト)。
 
kubectl applyでServiceを起動します。
| 1 2 3 4 5 6 7 8 | kubectl apply -f k8s/service.yaml service/template created # ローカルマシンのポート9999をServiceのポート8888に転送 kubectl port-forward service/template 9999:8888 Forwarding from 127.0.0.1:9999 -> 8888 Forwarding from [::1]:9999 -> 8888 | 
http://localhost:9999/ アクセスで、Serviceのポート経由でハロワを表示できます。
 
以上でk8sの基本的な機能を使ってDockerイメージを起動できました!
 
下記参考にした本です。k8sが実用的に説明されていてオススメです。