Level 1: アプリケーションをコンテナ化する¶
目的・ゴール: アプリケーションをコンテナ化する¶
今回はコンテナに適したアーキテクチャへ変更するまえの段階として、 オンプレミスで仮想マシンで動いているアプリケーションについてコンテナ化をしていきます。
コンテナ技術のDockerを使うことでクラウド、オンプレミス、PCなどどのような環境でもアプリケーションを稼働させることができます。
このレベルではラボで使用するKubernetes上で稼働させるアプリケーションのコンテナイメージを作成しデプロイするのが目標です。
流れ¶
- (Optional) Dockerfileを作成する。
- (Optional) ビルドを行いDockerイメージを作成
- (Optional) 作成したDockerイメージをイメージレジストリに登録
- アプリケーションのマニフェストファイルを作成、イメージレジストリに登録したイメージを使用
- アプリケーションをKubernetes上へデプロイ、稼働確認
コンテナ化の準備¶
本ラボでは以下のミドルウェアやスタックを使ったアプリケーションを想定しています。 基本的にはアプリケーションをコンテナ化する際にはDockerHubで作成済みのイメージを使用することで効率よくコンテナ化することができます。
Web/AP レイヤー
- nginx
- apache
- tomcat
Databaseレイヤー
- mySQL
- Postgress
- Oracle
- MongoDB
コンテナイメージの作成¶
このステップはアプリケーションを持ち込みの場合や複雑なスタックをコンテナ化する際に行うステップです。選択したアプリケーションによっては不要なステップになるのでやるべきかどうかを確認してください。
その場合、 アプリケーションのマニフェストファイルを作成してデプロイ からはじめてください。
想定するアプリケーションのコンテナイメージを作成します。
Dockerfile のリファレンス Dockerfile Reference ファイル
留意点としては以下の通りです。
アプリケーションの配置をDockerfile内に配置
基本となるコンテナイメージについてはDockerHubで探してベースイメージとする
静的な構成となっていないか(IPパスワードのべた書きなど)
- 環境変数で設定出来るよう設計する。のちほどk8sのSecretなどでパスワードを保存
冪等性はコンテナイメージ側で対応する。責任範囲を明確にしてイメージを作成
ステートフルなものについてはコンテナに適したものにする
- データ永続化については Level 2: ステートフルコンテナの実現 にて実施
ヒント
記述例を提示します。このままビルドしてもイメージは作成されませんのであくまで記述例としてみてください。 どうしても進まない場合は サンプル: 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にアクセスするとログイン画面が開きます。
ログイン・パスワードは以下のものを利用ください。
- user: user[ユーザ環境番号]
- pass: Netapp1!
ログインするとプロジェクト一覧が表示されます。
自身のユーザ名をクリックすると現在登録されているイメージが参照できます。 また同画面の「PUSH IMAGE」をクリックするとイメージのタグ付、レジストリへのpushの手順が提示されます。
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つを実施します。
どの部分を実施しているかを把握しながらすすめましょう。
- MySQL 用のSecretオブジェクトを作成
- MySQL をデプロイ
- 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を起動します。
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をデプロイします。
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が接続先を見つけるために使っている例が上記のマニフェストとなります。
- 参考URL: k8s label
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についても確認しましょう。
- 参考URL: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
注釈
kubectl引数の省略系について
今回はServiceの確認をする際に svc
という省略形でコマンドを実行しました。
他のオブジェクトも同様に省略形があります。コマンド入力を省力化したい場合は省略形も使ってみましょう。
kubectl --help
や kubectl XX --help
コマンドで確認できます。
まとめ¶
kubectlやYAMLで記載するマニフェストファイルを使ってk8sへのデプロイが体感できたかと思います。 実運用になるとこのYAMLをたくさん書くことは負荷になることもあるかもしれません.
その解決のためにパッケージマネージャーHelm 等を使ってデプロイすることが多いかと思います。 このラボでは仕組みを理解していただき、応用出来ることを目的としています。
ここまでで Level1 は終了です。