概要
KubernetesのPetSetの動作を自作のコンテナで理解する記事です。
Kubernetesの構築(記事はこちら)とDNSサーバーの構築(記事はこちら)が完了していることが前提となります。
PetSetについて
通常のReplication controllerなどでPodを区別なく横に並べるものではなく各Podを個別に区別し(連番のIDが振られるようです)ストレージの永続化や、固有のホスト名が与えられます。
また、Podが削除されても同じホスト名、同じストレージのマウントが保証されているようです。
Pod同士で通信が必要なモノやDBなどへの利用が考えられます。
詳しくは公式のドキュメントをご覧ください。
http://kubernetes.io/docs/user-guide/petset/
環境
DNSサーバーの構築(記事はこちら)の記事の環境がベースになっています。
masterサーバー | nodeサーバー | |
---|---|---|
ホスト名 | master | node1 |
IPアドレス | 192.168.137.20 | 192.168.137.21 |
動作しているサービス | kube-apiserver kube-controller-manager kube-scheduler kube-dns |
kubelet kube-proxy |
追加でnfsサーバーを別途用意し、各ノードにnfsクライアントのインストールをしてください。 (サンプルの例はmaster上でnfsサーバーを動かしています。)
また、ドメイン名がmmitti.infoであることにも注意してください。
構成
今回は2つのコンテナで構成されています。
- test-db
DBサーバ(実際はjsonファイルを読みだすだけ)
PetSetとして配置します
DockerHub上にmmitti/test-dbとしてイメージを公開しています
- test-db-client
testst-dbにアクセスしてHTMLを生成したりデータをポストするWebサーバー
DockerHub上にmmitti/test-db-clientとしてイメージを公開しています
test-db-clientからtest-dbへのアクセスは、テストのためサービス経由でアクセスするパターンと特定のホストにアクセスするパターンを用意しています。
サンプルコード
ここからさきで提示するyamlファイルはGithub上で公開しています。
cloneしてファイルを利用すると便利です。
ここからはクローンしたディレクトリ内で作業していると仮定してコマンドを示します。
PersistentVolumeの作成
PetSetのPodと接続するストレージを用意します。
/publicフォルダーがnfsサーバ(192.168.137.20)上で共有されていて、/public以下に01,02,03フォルダーが存在する状態と仮定してPersistentVolumeを作成します。
環境に合わせてyamlファイルを修正してください。
apiVersion: v1
kind: PersistentVolume
metadata:
name: dbpv01
annotations:
volume.beta.kubernetes.io/storage-class: "slow"
spec:
capacity:
storage: 10Mi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
path: /public/01
server: 192.168.137.20
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: dbpv02
annotations:
volume.beta.kubernetes.io/storage-class: "slow"
spec:
capacity:
storage: 10Mi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
path: /public/02
server: 192.168.137.20
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: dbpv03
annotations:
volume.beta.kubernetes.io/storage-class: "slow"
spec:
capacity:
storage: 10Mi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
path: /public/03
server: 192.168.137.20
以下のコマンドでPersistentVolumeを作成します。
kubectl create -f pv.yaml
以下のコマンドで正しく作成されたか確認します。
kubectl get pv
NAME CAPACITY ACCESSMODES STATUS CLAIM REASON AGE
dbpv01 10Mi RWX Available 3s
dbpv02 10Mi RWX Available 3s
dbpv03 10Mi RWX Available 3s
コンテナの配置
最初にtest-dbを配置します。
APIサーバーのスクリプトは/db以下にdat.jsonを生成しますので/dbをマウントしています。
test-db.yaml
apiVersion: v1
kind: Service
metadata:
name: test-db
labels:
app: test-db
spec:
ports:
- port: 8000
name: test-db
clusterIP: None
selector:
app: test-db
---
apiVersion: apps/v1alpha1
kind: PetSet
metadata:
name: test-db
spec:
serviceName: "test-db"
replicas: 2
template:
metadata:
labels:
app: test-db
annotations:
pod.alpha.kubernetes.io/initialized: "true"
spec:
terminationGracePeriodSeconds: 0
containers:
- name: test-db
image: mmitti/test-db
ports:
- containerPort: 8000
name: test-db
volumeMounts:
- name: pv
mountPath: /db
volumeClaimTemplates:
- metadata:
name: pv
spec:
accessModes: [ "ReadWriteMany" ]
resources:
requests:
storage: 5Mi
以下のコマンドでtest-dbを作成します。
kubectl create -f test-db.yaml
次にtest-db-clientを作成します。
APIサーバーのドメインを環境変数として渡します。
(ホスト名.サービス名.ネームスペース.ドメインで各ポッドにアクセスできるため API_PODという環境変数を用意しましたがあまり意味が無い気がします。APIと同じ値にしてください。)
kind: ReplicationController
apiVersion: v1
metadata:
name: test-db-client
labels:
app: test-db-client
spec:
replicas: 2
selector:
app: test-db-client
template:
metadata:
name: test-db-client
labels:
app: test-db-client
spec:
containers:
- name: test-db-client
image: mmitti/test-db-client
env:
- name: API
value: test-db.default.svc.mmitti.info:8000
- name: API_POD
value: test-db.default.svc.mmitti.info:8000
---
kind: Service
apiVersion: v1
metadata:
name: test-db-client
labels:
app: test-db-client
spec:
ports:
- name: tcp
protocol: TCP
port: 5000
targetPort: 5000
selector:
app: test-db-client
以下のコマンドでtest-db-clientを作成します。
kubectl create -f test-db-client.yaml
アクセスしてみる
http://192.168.137.20:8080/api/v1/proxy/namespaces/default/services/test-db-client:5000/
にアクセスるとtest-db-clientに接続されます。
この時test-db-clientでは環境変数APIに指定されたURL/info
にアクセスします。
この時ロードバランサー経由で接続されたいずれかのtest-dbポッドのホスト名を取得し
room/test-dbポッドのホスト名
にリダイレクトします。
以降test-db-clientは指定されたホスト名のtest-dbと通信しデータの読み書きを行います。
room/test-dbポッドのホスト名
の末尾の数字を0や1にして別のAPIサーバーに接続されていること、また、nfsサーバーのpublic/01とpublic/02内に生成されているjsonファイルなどを確認してみてください。
画面の詳しい見方や使い方はGithubのReadmeを御覧ください。
Podを削除してみる
PetSetとして配置したPodを削除してみます。
まず削除前のpodの一覧を確認します。
kubectl get po -l app=test-db
NAME READY STATUS RESTARTS AGE
test-db-0 1/1 Running 0 4m
test-db-1 1/1 Running 0 4m
次にpodを削除してみます
kubectl delete po -l app=test-db
少し待った後podの一覧を取得してみます。
kubectl get po -l app=test-db
NAME READY STATUS RESTARTS AGE
test-db-0 1/1 Running 0 10s
test-db-1 1/1 Running 0 5s
このように削除前と同じ名前で再生成されていることがわかると思います。
また、test-db-clientのWebページにアクセスしてもAPIサーバーのjsonファイルを生成したホスト名と現在jsonファイルを読みだしているホスト名が一致していると思います。
このようにホスト名が固定されストレージも対応付けを保ったまま永続化されていることが確認できると思います。