朝日ネット 開発者ブログ

朝日ネットのエンジニアによるリレーブログ。今、自分が一番気になるテーマで書きます。

microservicesはじめました (4)

前回起動するところまでこぎつけたMinikubeにサービスをデプロイしていきます。

おさらい

もう冷やし中華の季節も終わっているこの頃、このタイトルはいかがなものかと思いますがまだ続けます。 前回の記事ではローカル環境で動くKubernetesクラスタであるMinikubeを起動するところまでいきました。

環境は引き続き、CentOS 7をWindows 10でHyper-Vによって動かしています。

コンテナイメージの登録

Minikubeクラスタ内のレジストリにコンテナイメージを登録します。 環境変数を設定してイメージをビルドすればOKです。

eval $(minikube docker-env)
docker build -t grpc02-front:v1 .

これでMinikubeクラスタ内でイメージをpullできます。

Pod

まずKubernetesの概念であるPodについて書きます。 Podは1つ以上のコンテナと付随するリソース(ストレージやインタフェース)から構成されています。 KubernetesではPodを最小単位として扱います。

例として、nginxが動くPodは次のようなyamlファイルを作成して、

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.15-alpine
    ports:
    - containerPort: 80

kubectlコマンドを使うと作ることができます。 kubectl get pods とすると作られていることがわかります。

$ kubectl create -f nginx-pod.yaml
pod/nginx-pod created
$ kubectl get pods
NAME        READY     STATUS    RESTARTS   AGE
nginx-pod   1/1       Running   0          9s
$ kubectl delete pods nginx-pod
pod "nginx-pod" deleted

ReplicaSet

先ほどPodを作成しましたが、実用的にはPodを直接作成することは推奨されていません。 → “Naked” Pods vs ReplicaSets, Deployments, and Jobs

実際にはReplicaSetを作って、それを通してPodsを作ります。 ReplicaSetはPodsの集合なのですが、指定した数のPodsが動作していることを保証する仕組みがあり可用性・性能を確保することができます。

Deployment

Deploymentでは、PodsやReplicaSetの状態(Podの数など)を定義することができます。

次のようなyamlで設定します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: grpc02-front
spec:
  selector:
    matchLabels:
      app: front
  replicas: 2
  template:
    metadata:
      labels:
        app: front
    spec:
      containers:
      - name: front
        image: grpc02-front:v1
        ports:
        - containerPort: 80

.spec.replicasで、このPodが2つ動くことを指定しています。 .spec.template.spec.containersでPodに先ほど登録したイメージを動かすことにします。 .spec.template.metadata.labelsで、Podのラベルを定義しています。 ラベルを使って複数のPodsをまとめて操作できます。 このDeploymentは、.spec.selectorで、app: frontにマッチするPodsを制御するようにしています。

このyamlをクラスタに適用します。 指定した通り2つのPodsが動いています。

$ kubectl apply -f deploy-front.yaml
deployment.apps/grpc02-front created
$ kubectl get deployments
NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
grpc02-front   2         2         2            2           51s
$ kubectl get pods
NAME                            READY     STATUS    RESTARTS   AGE
grpc02-front-76b8cd789f-rm9gj   1/1       Running   0          55s
grpc02-front-76b8cd789f-wbjj6   1/1       Running   0          55s

Podを1つ(-rm9gj)削除してみると、自動で新しいPod(-xfkjp)が作成されます。

$ kubectl delete pods grpc02-front-76b8cd789f-rm9gj
pod "grpc02-front-76b8cd789f-rm9gj" deleted
$ kubectl get pods
NAME                            READY     STATUS    RESTARTS   AGE
grpc02-front-76b8cd789f-wbjj6   1/1       Running   0          14m
grpc02-front-76b8cd789f-xfkjp   1/1       Running   0          17s

Service

これでPodが動き始めましたが、Podはいつ消えるかわからず、PodのIPアドレスは変わることがあります。 安定してPodをクラスタ外部に公開したりPod間の通信をできるようにするべくServiceを設定します。

apiVersion: v1
kind: Service
metadata:
  name: grpc02-front
spec:
  selector:
    app: front
  ports:
  - protocol: TCP
    port: 80
  type: ClusterIP

.metadata.nameでServiceの名前を指定しています。ここで名前を付けることでクラスタ内のDNSを使ってこの名前でIPアドレスを直接指定することなくServiceにアクセスすることができます。1 .spec.typeClusterIPにして、クラスタ内のローカルIPを持つことを指定します。 外部に公開するときはNodePortを指定すればMinikubeクラスタ外部からのアクセスを設定できます。次の例ではPodの443番ポートをクラスタのIPアドレスで公開します。

  ports:
  - protocol: TCP
    port: 443
  type: NodePort

また、.spec.selector で、app: front のラベルを持つPodsを制御下に置くことを宣言します。

さて、そのservice定義を適用します。

$ kubectl apply -f service-front.yaml
service/grpc02-front created
$ kubectl get services
NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
grpc02-front   ClusterIP   10.104.162.3   <none>        80/TCP    3s
kubernetes     ClusterIP   10.96.0.1      <none>        443/TCP   1d
$ kubectl delete services grpc02-front
service "grpc02-front" deleted

うごかす

前回からKubernetesについて書いてきましたが、ようやく(2)で作成したサービスをMinikubeにデプロイします。

f:id:anmrtm:20180731145857p:plain

nginxのServiceだけをNodePortで外部に公開して他はClusterIPとします。

$ kubectl apply -f service.yaml
service/grpc02-nginx created
service/grpc02-front created
service/grpc02-api created
service/grpc02-geodec created
service/grpc02-address created
$ kubectl apply -f deploy.yaml
deployment.apps/grpc02-nginx created
deployment.apps/grpc02-front created
deployment.apps/grpc02-api created
deployment.apps/grpc02-maps created
deployment.apps/grpc02-address created
$ kubectl get services
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
grpc02-address   ClusterIP   10.106.23.74     <none>        5300/TCP        12s
grpc02-api       ClusterIP   10.109.177.176   <none>        80/TCP          13s
grpc02-front     ClusterIP   10.103.38.240    <none>        80/TCP          13s
grpc02-maps      ClusterIP   10.106.142.85    <none>        5300/TCP        12s
grpc02-nginx     NodePort    10.110.178.202   <none>        443:31789/TCP   13s
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP         21d

minikube service で公開しているIPアドレス・ポート番号を得ます。 curlでそのアドレス・ポートにアクセスすると200が返ってくることが確認できます。

$ minikube service grpc02-nginx --url
http://192.168.39.223:31073
$ curl -k -I https://192.168.39.223:31073
HTTP/1.1 200 OK
Server: nginx/1.15.4
Date: Mon, 22 Oct 2018 02:18:02 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive

まとめ

Minikubeクラスタ上にサービスをデプロイすることができました。 しかし現状ではCentOSからしかアクセスできていないので、次回でホストOSのWindowsからもアクセスができるようにしていきます。

採用情報

朝日ネットでは新卒採用・キャリア採用を行っております。


  1. 環境変数で得る方法もあります。