Docker/Kubernetes 実践コンテナ開発入門@30日目

Docker/Kubernetes 実践コンテナ開発入門:書籍案内|技術評論社

前回は、TODOAPI を構築しました。

今回も同じように TODO Web アプリケーションを構築して、Ingress で Web アプリケーションをインターネットに公開していきます。

6.5 TODO Web アプリケーションを GKE 上に構築する

  • todo-web.yaml
    • 静的ファイル(assets)は Node.js を通さず Nginx から返す方法を取る
    • nginx コンテナと web コンテナで Pod を構成
apiVersion: v1
kind: Service // Serviceリソース
metadata:
  name: todoweb // Serviceリソースの名前はtodoweb
  labels:
    app: todoweb // Serviceリソースのラベルはapp: todoweb
spec: // Serviceリソースの仕様
  selector:
    app: todoweb // app: todowebラベルを持つPodが対象
  ports:
    - name: http
      port: 80 // app: todowebラベルのhttpポート80を持つPodが対象。またService自身のポートは80
  type: NodePort // 指定されたレンジのポートを割り当て、Nodeはそのポートへの通信をServiceに割り当てる。

---
apiVersion: apps/v1
kind: Deployment // Deploymentリソース
metadata:
  name: todoweb // Deploymentリソースの名前はtodoweb
  labels:
    name: todoweb // Deploymentリソースのラベルはname: todoweb
spec:
  replicas: 2 // Podのレプリカは2
  selector:
    matchLabels:
      app: todoweb // 対象はapp: todowebラベルを持つPod
  template: // Pod Template
    metadata:
      labels:
        app: todoweb // Podのラベルはapp: todoweb
    spec:
      volumes: # ← ①
      - name: assets // assetsという名称のVolumeを作成
        emptyDir: {} // Pod単位に割り当てられる仮想Volumeを作成。Podが削除されると削除される。
      containers: // コンテナ定義
      - name: nginx // コンテナ名
        image: gihyodocker/nginx-nuxt:latest // コンテナイメージ
        imagePullPolicy: Always // ローカルにキャッシュイメージがあればそれを使用。なければイメージをダウンロードしてくる
        ports:
        - containerPort: 80 // コンテナのポート。同一Pod内で衝突しないように。
        env:
        - name: WORKER_PROCESSES
          value: "2"
        - name: WORKER_CONNECTIONS
          value: "1024"
        - name: LOG_STDOUT
          value: "true"
        - name: BACKEND_HOST
          value: "localhost:3000" // 同じPod内のwebコンテナを指している
        volumeMounts: # ← ②
        - mountPath: /var/www/_nuxt // マウントするコンテナのパスを指定
          name: assets // 仮想Volumeのassetsでマウント

      - name: web
        image: gihyodocker/todoweb:latest
        imagePullPolicy: Always
        lifecycle: # ← ③
          postStart:
            exec:
              command:
              - cp
              - -R
              - /todoweb/.nuxt/dist
              - /
        ports:
        - containerPort: 3000
        env:
        - name: TODO_API_URL
          value: http://todoapi // Service名をURLにしたもの
        volumeMounts: # ← ④
        - mountPath: /dist
          name: assets
  • todo-web をデプロイ
$ kubectl apply -f todo-web.yaml
service/todoweb created
deployment.apps/todoweb created
  • 仮想 Volume によってコンテナ間のディレクトリ共有が可能に。

  • web コンテナの assets ファイルを Nginx コンテナにコピーする必要がある。 => Lifecycle イベントを利用

  • Lifecycle イベント

    • コンテナの開始時や終了時のタイミングで任意のコマンドを実行するための仕組み
  • postStart を使って web コンテナの開始時に、仮想 Volume に assets ファイルをコピーする

  • postStart.exec.command で次のコマンドを実行しており、/dist ディレクトリに assets ファイルがコピーされる

@web $ cp -R /todoweb/.nuxt/dist /
  • /dist ディレクトリは assets ボリュームに共有される
  • assets ボリュームを nginx コンテナもマウントしているため、/var/www/_nuxt/に assets が配置される

6.6 Ingress で Web アプリケーションをインターネットに公開する

  • Ingress を利用して Web アプリケーションをインターネットに公開する

  • GCP では Cloud Load Balancing が利用される

  • ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress // Ingressリソース
metadata:
  name: ingress // Ingerssリソースの名前はingress
spec:
  rules: // Ingressが受けたリクエストのパス毎にバックエンドに転送。全てをtodowebに転送
  - http:
      paths:
      - path: /*
        backend:
          serviceName: todoweb
          servicePort: 80
  • ingress をデプロイ
$ kubectl apply -f ingress.yaml
ingress.extensions/ingress created
  • Ingress が作成されると、1 分程でグローバル IP アドレスが振られる
$  kubectl get ingress
NAME      HOSTS   ADDRESS         PORTS   AGE
ingress   *       35.xxx.xxx.xx   80      4m52s
  • そこから完全に準備が整うまで数分かかる

Ingressのステータス

  • ステータスが OK になったら準備完了

Ingressのステータス

  • Ingress で公開されたグローバル IP アドレスにアドレスにアクセスすると TODO アプリケーションをみることができます。

TODO List

  • Docker のときはスタイルが崩れちゃっていましたが今回はうまくいったようです!!

今日の学び

  • Ingress でインターネットからのリクエストを Service に委譲するために Service は NodePort で公開する。
  • 仮想 Volume を作ると、Pod 内でそれぞれのコンテナから好きなパスでアクセスできる
Hugo で構築されています。
テーマ StackJimmy によって設計されています。