DeploymentとServiceをyamlファイルで定義する
kubectlコマンドとオプションでnginxをminikube上で動かしました。 今回は、コマンドで起動内容を指定するのではなく、定義ファイルを使って動かすようにします。定義ファイルにすることでgitで管理できるようになります。
コマンドの振り返り
以下のように起動して、接続できるようにしまていました。
# nginxの起動 kubectl run nginx --image=nginx:1.11 --port=80 # Macから接続できるように kubectl expose deploy nginx --name=nginx-nodeport --port=80 --target-port=80 --type="NodePort"
これは実際に何をやっているかというと、Deploymentという機能を使ってnginxコンテナを起動し、Serviceを使ってnginxコンテナにアクセスできるようにしています。
Deployment
Deploymentは、複数のコンテナを並列起動し、世代管理できる仕組みです。今回Deployment(+ReplicaSet, Pod)自体が何かというのはあまり重要ではないので省略。以下の記事で細かく解説されています。
Service
Serviceは複数のコンテナへのアクセスを仲介してくれるロードバランサーです。個々のコンテナのアクセス方法を把握しなくても、Serviceの受付口だけ知っていれば、通信できます。
定義ファイル(yaml)にする
定義ファイルはJSONとyaml形式が使えます。他のプログラムを仲介する場合はJSONが良さそうですが、設定管理なら個人的にはyamlが好きです。(コメントアウトやコメント書ける点が良い)
nginx-deploy.yml
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx spec: replicas: 2 template: metadata: labels: run: nginx spec: containers: - name: nginx image: nginx:1.11 ports: - containerPort: 80
kubectl run
で指定していたもの+を定義します。
プロパティ | 説明 |
---|---|
apiVersion | Deploymentはベータ開発中なので、extentions/v1betaだそうです *1 |
kind | kubectl run で動かしていたので、隠れていましたが、実態はDeploymentなので明示します。 |
metadata.name | kubectl run の後に指定していた名前 |
spec.replicas | --replicas オプションで指定できる、レプリカ数(コンテナの並列数) |
spec.template. metadata.labels |
識別するための任意のKeyValue |
spec.template.spec. containers.name |
コンテナの名前 |
spec.template.spec. containers.image |
--image オプションで指定していたコンテナイメージ |
spec.template.spec. containers.ports. containerPort |
--port オプションで指定したコンテナの公開しているポート |
続いてSerivce。kubectl expose
で指定したもの+を定義します
service.yml
apiVersion: v1 kind: Service metadata: name: nginx-nodeport spec: type: NodePort ports: - port: 80 protocol: TCP targetPort: 80 selector: run: nginx
プロパティ | 説明 |
---|---|
apiVersion | ServiceはDeploymentと異なりv1です。 |
kind | 同様にkubectl expose を使っていましたがServiceを明示します。 |
metadata.name | --name オプションで指定していたもの |
spec.type | --type オプションで指定していたもの |
spec.ports.port | --port で指定したいたもの |
spec.ports.protocol | TCPを明示 |
spec.ports.targetPort | は--target-port で指定していたコンテナに対するポート |
spec.selector | 前述のDeploymentのlabelと関係します。後で詳しく。 |
起動
kubectl create
コマンドで作成(起動)します。
kubectl create -f nginx-deployment.yml kubectl create -f service.yml
-f
は同時に複数指定も可能です。
kubectl create -f nginx-deployment.yml -f service.yml
minikube経由でブラウザ起動して確認。nginxのwelcomeページが見れます。
minikube service nginx-nodeport
DeploymentのlabelとServiceのselector
kubectl expose
コマンドは、その後にdeploy nginx
と指定していました。これはnginxという名前
のdeploymentをターゲットにするという意味です。定義ファイルの場合は、labelとselectorで紐付けが行われています。
Serviceのselectorで指定したkey:valueと一致するDeployment*2に、リクエストを流すようになります。
run: nginx
を指定していますが、特にrunというkeyにしなくても、Deploymentのlabelをapp: httpserver
にして、Serviceのselectorも同様に指定することでもリクエストが流れます。一致すればOKです。
Deployment以外にもlabelやselectorを書けるので、nameよりも柔軟に対象を決めることができるようです。
Labels and Selectors | Kubernetes
いろいろなところで、deploy nginxなど、いちいち名前を書いてられないので、labelをつけて、複数のターゲットを同一label名で識別できるようにすることを目的としているようです。でもlabelは多分もうちょっと詳しく調べないとよくわからず。
参考
- kubernetes - apiVersion and beta versions - Stack Overflow
- Labels and Selectors | Kubernetes
- Kubernetes: Deployment の仕組み - Qiita
*1:http://stackoverflow.com/questions/38547229/apiversion-and-beta-versions
*2:DeploymentじゃなくReplicaSetかもしれない?
Linuxでメモリ使用量が増え続けた
AmazonLinux 2017.03にnginx乗せて稼働させてたら、なぜかメモリ使用量が、1日ちょっとで2GB後半にさしかかりました。cacheではなくusedを徐々に消費してたので、これは何かリークしてる疑い。
プロセス等を見てもメモリを使っているものもいないし、疑いのあるプロセスをrestartしても改善しませんでした。
何だろうなーと調べてみたらすぐ出てきました。特にAmazonLinuxは関係なし。
上記ページと同じく、NSSの問題で、curlがdentryというディレクトリ階層構造の管理をしているキャッシュを多く消費してしまうと。curlでhttpsの監視が動いており、それが5分に1回なので、徐々にリークした様子。1時間に100MB程度ずつ増加していたようです。
回避策は、NSS_SDB_USE_CACHE=YES
という環境変数を指定すること。とりあえず監視スクリプトにexport NSS_SDB_USE_CACHE=YES
を追加したら、増加が止まりました。
溜まったキャッシュは、以下のようにして解放されました。
echo 2 > /proc/sys/vm/drop_caches
>>
でも>
でもどっち動きますが多分>
の方が適切?2
という値は対象のキャッシュによって異なります。
値 | クリアする対象キャッシュ |
---|---|
1 | ページキャッシュ |
2 | dentry,inode |
3 | ページキャッシュ,dentry,inode |
まとめ
じわじわ増えてく系のメモリリークは怖いです。調べたらたくさん出てきたので、割とメジャーな要因みたいですね。
Slabは知らなかったので調べてみたら、ざっくり言うとカーネル側のキャッシュとのこと。細かいメモリ周りはやっぱよくわかってない感。
参考
minikubeで自分の作ったimageを使う
前回minikubeの実行環境を作りました。公開されているnginxのimageを使いましたが、実際は自分でimageを作成し、それを実行させることがほとんどだと思います。minikubeはdockerを内包しているので、そこでdocker buildすればimageが登録され、使うことができます。
nginxに静的ページを追加したコンテナを作って試す
まず、minikubeのdockerを使うために以下を実行します。
eval $(minikube docker-env)
次にお試し用のpage.htmlとDockerfileを作ります。
# page.html echo '<html> <head><title>this is page</title></head> <body>original page</body> </html>' > page.html # Dockerfile echo 'FROM nginx:1.11 COPY page.html /usr/share/nginx/html/page.html' > Dockerfile
ファイル構成としてはこんな形になります。
k8s/ ・・・名前はなんでもよくここにいる状態でeval $(minikube docker-env) |- Dockerfile +- page.html
imageを作ります。タグはlatestだと動かないので、適当にバージョンつけます。
docker build -t example/nginxpage:0.1.0 .
k8sで動かします。
# コンテナ起動 kubectl run nginxpage --image=example/nginxpage:0.1.0 --port=80 # Macからアクセスできるように kubectl expose deploy nginxpage --name=nginxpage-nodeport --type="NodePort"
ブラウザで確認します。
minikube service nginxpage-nodeport
標準ブラウザが立ち上がり、nginxのwelcomeページが表示されるので、URL欄に/page.html
を追加します。
そうすると、original page
と表示され、自分で作ったコンテナが利用できていることがわかります。