Level 1: アプリケーションをコンテナ化する

目的・ゴール: アプリケーションをコンテナ化する

今回はコンテナに適したアーキテクチャへ変更するまえの段階として、 オンプレミスで仮想マシンで動いているアプリケーションについてコンテナ化をしていきます。

コンテナ技術のDockerを使うことでクラウド、オンプレミス、PCなどどのような環境でもアプリケーションを稼働させることができます。

このレベルではラボで使用するKubernetes上で稼働させるアプリケーションのコンテナイメージを作成しデプロイするのが目標です。

流れ

  1. (Optional) Dockerfileを作成する。
  2. (Optional) ビルドを行いDockerイメージを作成
  3. (Optional) 作成したDockerイメージをイメージレジストリに登録
  4. アプリケーションのマニフェストファイルを作成、イメージレジストリに登録したイメージを使用
  5. アプリケーションをKubernetes上へデプロイ、稼働確認

コンテナ化の準備

本ラボでは以下のミドルウェアやスタックを使ったアプリケーションを想定しています。 基本的にはアプリケーションをコンテナ化する際にはDockerHubで作成済みのイメージを使用することで効率よくコンテナ化することができます。

Web/AP レイヤー

  • nginx
  • apache
  • tomcat

Databaseレイヤー

  • mySQL
  • Postgress
  • Oracle
  • MongoDB

コンテナイメージの作成

このステップはアプリケーションを持ち込みの場合や複雑なスタックをコンテナ化する際に行うステップです。
選択したアプリケーションによっては不要なステップになるのでやるべきかどうかを確認してください。

その場合、 アプリケーションのマニフェストファイルを作成してデプロイ からはじめてください。

想定するアプリケーションのコンテナイメージを作成します。

Dockerfile のリファレンス Dockerfile Reference ファイル

留意点としては以下の通りです。

  • アプリケーションの配置をDockerfile内に配置

  • 基本となるコンテナイメージについてはDockerHubで探してベースイメージとする

  • 静的な構成となっていないか(IPパスワードのべた書きなど)

    • 環境変数で設定出来るよう設計する。のちほどk8sのSecretなどでパスワードを保存
  • 冪等性はコンテナイメージ側で対応する。責任範囲を明確にしてイメージを作成

  • ステートフルなものについてはコンテナに適したものにする

ヒント

記述例を提示します。このままビルドしてもイメージは作成されませんのであくまで記述例としてみてください。 どうしても進まない場合は サンプル: Dockerfile記述例 をクリックしてください。

コンテナイメージのビルド

作成した Dockerfileをビルドしてイメージを作成します。

バージョニングを意識してコンテナイメージを作成します、コンテナイメージに明示的にバージョンを指定します。

$ docker build -t 生成するコンテナイメージ名:タグ名 Dockerファイルのパス

Dockerイメージの生成方法は複数の手法があります。 例えば、普通のOSイメージを起動して、ログインしパッケージなどのインストールを行っていく手法があります。 メリットとしてはオペレーションで作成したものをイメージとして登録できるため、Dockerfileを作成しなくても良いといメリットがある一方で、 コンテナイメージの作成方法が不透明となる可能性もあります。

イメージレジストリに登録

プライベートレジストリ、DockerHubは選択いただけます。 このラボで作成したイメージを自社などで再利用したい場合はDockerHubにpushすることもできます。

DockerHub へログイン

DockerHubにアカウントがあることが前提です。

$ docker login

  ユーザ名、パスワードを入力

$ docker image push アカウント名/コンテナイメージ名:タグ名

Private registry (Harbor) を使う場合

private registry を使う場合はラボ内にHarborを準備しています。

Harbor URL: https://registry.ndxlab.net/

本ラボではプロジェクトを事前準備しており、コンテナイメージのレジストリとして使用できます。 Harborへログインしてみましょう。上記のURLにアクセスするとログイン画面が開きます。

../../_images/harbor-login.png

ログイン・パスワードは以下のものを利用ください。

  • user: user[ユーザ環境番号]
  • pass: Netapp1!

ログインするとプロジェクト一覧が表示されます。

../../_images/harbor-project-list.png

自身のユーザ名をクリックすると現在登録されているイメージが参照できます。 また同画面の「PUSH IMAGE」をクリックするとイメージのタグ付、レジストリへのpushの手順が提示されます。

../../_images/harbor-push-image.png

Dockerイメージのビルド、pushのサンプルは以下の通りです。

$ docker login https://registry.ndxlab.net
$ docker tag  pets_object_detection  registry.ndxlab.net/user[ユーザ環境番号]/pets_object_detection:1.0
$ docker push registry.ndxlab.net/user[ユーザ環境番号]/pets_object_detection:1.0

アプリケーションのマニフェストファイルを作成してデプロイ

Level 0: 環境の確認・基本操作 ではコマンドラインで作成してきましたがYAMLファイルで1サービスをまとめてデプロイ出来るようにします。

ファイルのセクション構成としては以下の通りです。

  • Service
  • PersistentVolumeClaim
  • Deployment

サンプルファイルを準備しましたのでそれぞれの項目の意味を考え作成してみましょう。

(https://kubernetes.io/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/ を参考としています。)

ここではサンプルとしてWordPressとMySQLをデプロイします。 MySQLではSecretオブジェクトを使用しパスワードを渡すようになっています。

流れとしては、以下の3つを実施します。

どの部分を実施しているかを把握しながらすすめましょう。

  1. MySQL 用のSecretオブジェクトを作成
  2. MySQL をデプロイ
  3. WordPressをデプロイ

Secretの作成

ここではKubernetes上でパスワードを受け渡すときなどに使う、Secretを作成します。

Secretの説明はこちらです。

$ kubectl create secret generic mysql-pass --from-literal=password=YOUR_PASSWORD

作成後は以下のコマンドで結果を確認します。

$ kubectl get secrets

     NAME                  TYPE                    DATA      AGE
      mysql-pass            Opaque                  1         42s

MySQLのデプロイ

mysql-pass という名前でSecretができたのでそのSecretを使ってMySQLを起動します。

アプリケーションをデプロイするマニフェストファイルの例 mysql-deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
        - image: mysql:5.6
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-pass
                  key: password
          ports:
            - containerPort: 3306
              name: mysql

上記のマニフェストをもとにDeploymentを作成します。

kubectl create -f mysql-deployment.yaml

少々時間がかかるのでどのように状態が移って行くか確認し、「Status」が「Running」になることを確認してください。

$ kubectl get pods

NAME                               READY     STATUS    RESTARTS   AGE
wordpress-mysql-1894417608-x5dzt   1/1       Running   0          40s

WordPressのデプロイ

MySQLのコンテナが立ち上がったらそのMySQLに接続するWordPressをデプロイします。

アプリケーションをデプロイするマニフェストファイルの例 wordpress-deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - port: 80
  selector:
    app: wordpress
    tier: frontend
  type: LoadBalancer
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
        - image: wordpress:4.8-apache
          name: wordpress
          env:
            - name: WORDPRESS_DB_HOST
              value: wordpress-mysql
            - name: WORDPRESS_DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-pass
                  key: password
          ports:
            - containerPort: 80
              name: wordpress

MySQLと同様にデプロイします。

kubectl create -f wordpress-deployment.yaml

kubectlの操作を容易にする

上記のマニフェストにも記載がありますが、Labelには複数の使い方があります。 Serviceが接続先を見つけるために使っている例が上記のマニフェストとなります。

kubectlのオペレーションの簡易化のためlabelをつけることをおすすめします。 例えば以下のような使い方があります。

kubectl get pods -l app=nginx などのようにlabelがついているPod一覧を取得といったことが簡単にできます。 ほかにも以下の様なことが可能となります。

  • kubectl delete deployment -l app=app_label
  • kubectl delete service -l app=app_label
  • kubectl delete pvc -l app=wordpress

アプリケーションの稼働確認

デプロイしたアプリケーションにアクセスし正常稼働しているか確認します。

アクセスするIPについてはサービスを取得して確認します。

$ kubectl get svc

結果として以下のような出力が得られます。

今回はService.typeをLoadBalancerで指定しているため、EXTERNAL-IP欄に表示されたIPでアクセスしてみましょう。

NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes        ClusterIP   10.96.0.1      <none>        443/TCP        6d
wordpress         LoadBalancer    10.98.247.58   192.168.10.210        80:32048/TCP   2h
wordpress-mysql   ClusterIP   None           <none>        3306/TCP       2h
  • 今回はオンプレミスでMetalLBを使用しLoadBalancerでExternal-IPを使用できるようにしました。

Service.Type=NodePortについても確認しましょう。

注釈

kubectl引数の省略系について

今回はServiceの確認をする際に svc という省略形でコマンドを実行しました。 他のオブジェクトも同様に省略形があります。コマンド入力を省力化したい場合は省略形も使ってみましょう。

kubectl --helpkubectl XX --help コマンドで確認できます。

まとめ

kubectlやYAMLで記載するマニフェストファイルを使ってk8sへのデプロイが体感できたかと思います。 実運用になるとこのYAMLをたくさん書くことは負荷になることもあるかもしれません.

その解決のためにパッケージマネージャーHelm 等を使ってデプロイすることが多いかと思います。 このラボでは仕組みを理解していただき、応用出来ることを目的としています。

ここまでで Level1 は終了です。