LoginSignup
4
1

More than 3 years have passed since last update.

MacのDocker DesktopでさくっとKubernetesコンテナを動かしてみる。

Posted at

Kubernetesはどこのパブリッククラウドでも動くようになってるしすごいですね。

ただ、今回は手持ちのMacで動かしてみたいと思います。Docker Desktopはインストールされている前提です。

Mac:KubernetesをONにする。

k8s.png

Docker DesktopアプリのPreferenceから、Kubernetesを有効にしてください。起動には結構時間がかかりますので次のステップを進めておきましょう。

サンプルのダウンロード

VSCodeの拡張機能でサクッとGKEにデプロイできるCloud Codeというのがあります。
これのサンプルでcloud-code-samplesをダウンロードします。

デスクトップなどでもどこでもいいです。そしてnodejsのサンプルにはいってください。

cd ~/Desktop
git clone https://github.com/GoogleCloudPlatform/cloud-code-samples.git
cd cloud-code-samples/nodejs/nodejs-hello-world/

ファイルはこんな感じになってるはずです。

.
├── Dockerfile
├── README.md
├── img
│   └── diagram.png
├── kubernetes-manifests
│   ├── hello.deployment.yaml
│   └── hello.service.yaml
├── package-lock.json
├── package.json
├── skaffold.yaml
└── src
    └── app.js

ここのREADMEにもあるようにGKEをつかうならコマンド一発でできるそうです。

skaffold run --default-repo=gcr.io/your-project-id-here/cloudcode

ローカルで頑張るには少し作業が必要です。skaffoldの設定でもできるのかもしれませんがよくわからないので使いません(教えてくださいw)

app.jsを少し変更する

あとでわかりやすいようにapp.jsを少し変えます。一ヶ所だけです。

src/app.js
const express = require('express');

const app = express();

// returns a simple respnse 
app.get('/', (req, res) => {
  console.log(`received request: ${req.method} ${req.url}`);
  res.status(200).send(`Hello, world! - ${process.env.HOSTNAME}`); // ここを変更
});

// starts an http server on the $PORT environment variable
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});

module.exports = app

Dockerfileをビルドしてイメージを作成する

直下のDockerfileをビルドします。
イメージ名はnode-hello-worldです。

docker build -t node-hello-world:latest .

これでイメージもできました。

$ docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
node-hello-world                     latest              f1204ec69435        6 seconds ago       921MB

マニフェストファイルを変更

Dockerだけならこの段階で動かせるぜ!となりますが、サンプルプロジェクトのKubernetesマニフェストはすこし変更が必要です。
ついでに稼働するPod数も1つではつまらないので3つにしてみます。
kubernetes-manifests/hello.deployment.yaml を変更します。
replicasを3にするのと、imagePullPolicy: Neverというのを追加します。

kubernetes-manifests/hello.deployment.yaml
# This Deployment manifest defines:
# - single-replica deployment of the container image, with label "app: node-hello-world"
# - Pod exposes port 8080
# - specify PORT environment variable to the container process
# Syntax reference https://kubernetes.io/docs/concepts/configuration/overview/
apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-hello-world
spec:
  ### ↓ 3に増やす ###
  replicas: 3
  selector:
    matchLabels:
      app: node-hello-world
  template:
    metadata:
      labels:
        app: node-hello-world
    spec:
      containers:
        - name: server
          image: node-hello-world
          ### ↓ これを追加 ###
          imagePullPolicy: Never
          ports:
          - containerPort: 8080
          env:
          - name: PORT
            value: "8080"

imagePullPolicy:とは、イメージをどこから取ってくるかの設定です。Neverにしとけばローカルに作成したイメージを使ってくれるとのことです。

By default, the kubelet will try to pull each image from the specified registry. However, if the imagePullPolicy property of the container is set to IfNotPresent or Never, then a local image is used (preferentially or exclusively, respectively).

実行!

いよいよ実行してみます。kubernetes-manifests以下の2つのマニフェストファイルを使いますので下記コマンドのようになります。

kubectl apply -f kubernetes-manifests

こんな表示がでます。

deployment.apps/node-hello-world configured
service/node-hello-world-external unchanged

次に状態を見てみましょう。

kubectl get pods,services

起動中だとステータス違いますがしばらく立ってうまく起動してるとこんな表示になるはずです。

NAME                                   READY   STATUS    RESTARTS   AGE
pod/node-hello-world-5f6c8599c-758wv   1/1     Running   0          13s
pod/node-hello-world-5f6c8599c-q4jqp   1/1     Running   0          13s
pod/node-hello-world-5f6c8599c-xfdl7   1/1     Running   0          13s

NAME                                TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/kubernetes                  ClusterIP      10.96.0.1        <none>        443/TCP        156m
service/node-hello-world-external   LoadBalancer   10.108.217.246   localhost     80:30063/TCP   126m

LoadBalancerとしてnode-hello-world-externalが動いていて、そこにぶら下がるPodが3つというわけですね。

動作確認

curlで見てみます。

curl http://localhost/

こんな結果が返ってきました。なるほど、HOST_NAMEがPodの名前になっていますね。

Hello, world! - node-hello-world-5f6c8599c-xfdl7

3つのPodが動いているはずなので他のPodからのレスポンスは返ってくるでしょうか?

sh-3.2$ for i in {1..10};do echo `curl -s http://localhost/`;done
Hello, world! - node-hello-world-5f6c8599c-xfdl7
Hello, world! - node-hello-world-5f6c8599c-xfdl7
Hello, world! - node-hello-world-5f6c8599c-758wv
Hello, world! - node-hello-world-5f6c8599c-q4jqp
Hello, world! - node-hello-world-5f6c8599c-758wv
Hello, world! - node-hello-world-5f6c8599c-q4jqp
Hello, world! - node-hello-world-5f6c8599c-758wv
Hello, world! - node-hello-world-5f6c8599c-758wv
Hello, world! - node-hello-world-5f6c8599c-xfdl7
Hello, world! - node-hello-world-5f6c8599c-758wv

お〜いい感じです。

ロードバランサはいい感じで分散してくれるのでしょうか?

sh-3.2$ for i in {1..99};do echo `curl -s http://localhost/`;done | sort | uniq -c
  33 Hello, world! - node-hello-world-5f6c8599c-758wv
  34 Hello, world! - node-hello-world-5f6c8599c-q4jqp
  32 Hello, world! - node-hello-world-5f6c8599c-xfdl7

お〜、これまたいい感じ。

イメージを更新したらrollout

Dockerイメージを作り直した際にはrolloutしましょう。

hello.deployment.yamlを更新します。

sh-3.2$ kubectl rollout restart -f kubernetes-manifests/hello.deployment.yaml
deployment.apps/node-hello-world restarted

すかさず状態をみるとこんな感じです。

sh-3.2$ kubectl get pods,services
NAME                                    READY   STATUS              RESTARTS   AGE
pod/node-hello-world-58d65988bc-fqhmn   0/1     ContainerCreating   0          0s
pod/node-hello-world-58d65988bc-zdh5f   1/1     Running             0          2s
pod/node-hello-world-5f6c8599c-758wv    1/1     Running             0          49m
pod/node-hello-world-5f6c8599c-q4jqp    1/1     Terminating         0          11m
pod/node-hello-world-5f6c8599c-xfdl7    1/1     Running             0          11m

NAME                                TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/kubernetes                  ClusterIP      10.96.0.1        <none>        443/TCP        168m
service/node-hello-world-external   LoadBalancer   10.108.217.246   localhost     80:30063/TCP   137m

Podが入れ替わってますね。入れ替わってる最中もアクセスできますし、しばらくすると安定します。

終了

サービスを停止します。Podを単独で停止してもすぐ復旧しちゃうので元から止めましょう。

sh-3.2$ kubectl delete -f kubernetes-manifests/
deployment.apps "node-hello-world" deleted
service "node-hello-world-external" deleted

止まりましたかね?確認してみます。

sh-3.2$ kubectl get pods,services

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   174m

大丈夫そうです。

プログラムはどうでしょう?

sh-3.2$ curl http://localhost/
curl: (7) Failed to connect to localhost port 80: Connection refused

ばっちりですね。

それにしても...

Kubernetesすごいな〜(Macが重くなるけど...)

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1