こんにちは、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が実用的に説明されていてオススメです。