2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

K8s on Vagrant HACMP相当の高可用性の動作検証メモ

Last updated at Posted at 2018-04-23

k8s v1.10 をvagrantの仮想環境上で動作させて、iSCSIディスクを共有ディスクとして、ノード障害時のテイクオーバーの動作を検証したメモです。

vagrantの仮想サーバーで、k8s v1.10のクラスタを動作させて検証した4回目の記事で、これまでの記事を列挙しておきます。

システム構成

iSCSIターゲット(サーバー)をk8sクラスタ外部に構成して、k8sクラスタ内のポッドからiSCSIの永続ディスクを利用します。 NFSの様にネットワーク上で複数のクライアントのファイル共有を目的として開発されたソフトウェアと異なり、iSCSIは、コンピュータと周辺機器を接続するために開発されたSCSIをTCP/IPネットワーク上で利用するためのソフトウェアです。 そのため、次の図の様に、同時に一つのポッドのみ接続を行う必要があります。

スクリーンショット 2018-04-23 22.22.26.png

例えば、iSCSIターゲットが提供するボリュームは、複数のイニシエータ(クライアント)からの同時書き込みに用いることができません。
スクリーンショット 2018-04-23 22.23.10.png

しかし、RDBなどのデータベースのソフトウェアは、SCSIを用いたディスクアクセス環境上で、トランザクションの一貫性を維持しながら、パフォーマンスを確保するための機構を備えたソフトウェアです。 ハイエンドUNIXサーバーなどでは、ファイバーチャネルのストレージ・エリアネットワークを用いることがありますが、このファイバーチャネルも SCSIの規格で定められたプロトコルを通す仕組みとなっており、iSCSIと同じ制約を持っています。

RDBMSのコンテナ化されたソフトウェアとiSCSIを組み合わせることで、ファイバーチャンネルを利用するのに近いパフォーマンスで、k8s上でアクティブ・スタンバイの高可用性の構成を作ることができます。例えば、次の図で表すイメージになります。

スクリーンショット 2018-04-23 22.23.54.png

今回は、MySQLとiSCSIのボリュームで、k8sのデプロイメントの機能で、アクティブ・スタンバイの構成を作り、アプリケーションがアクセスするVIPに相当する固定のIPアドレスを k8s のサービス Cluster IPを利用して構築してみます。

iSCSIサーバーの構築用Vagrantfile

iSCSIのターゲットとイニシエータの機能を作るために、下記のVagrantfileを作成しました。 このスクリプトによって、ボリュームを提供するiSCSIサーバー(ターゲット)と、クライアントのサンプルとしてのiSCSIイニシエータの二つの仮想サーバーを起動します。 目的の構成では、イニシエーターは、MySQLが稼働するポッドになりますが、テスト用として仮想サーバー上にイニシエータを同時に作成します。

# coding: utf-8
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/xenial64"
  hosts = Array["target", "initiator"]
  ip_x = 0
  hosts.each do |host|
    config.vm.define vm_name = "#{host}" do |config|
      config.vm.hostname = host
      public_ip = "192.168.1.#{ip_x+70}"
      ip_x = ip_x + 1      
      config.vm.network :public_network, ip: public_ip, bridge: "en0: Ethernet"
      #
      config.vm.provider "virtualbox" do |vb|
        vb.gui = false
        vb.memory = "512"
      end
      
      # iscsiイニシエータ (クライアント)
      if host == "initiator" then
        target_ip = "#{public_ip}"
        config.vm.provision "shell", inline: <<-SHELL
        apt-get update
        apt-get install -y open-iscsi
        sed 's/^InitiatorName=/InitiatorName=iqn.2016-04.world.srv:target00/' -i /etc/iscsi/initiatorname.iscsi
        sed 's/^#node.session.auth.authmethod = CHAP/node.session.auth.authmethod = CHAP/' -i /etc/iscsi/iscsid.conf
        sed 's/^#node.session.auth.username = username/node.session.auth.username = username/' -i /etc/iscsi/iscsid.conf
        sed 's/^#node.session.auth.password = password/node.session.auth.password = password/' -i /etc/iscsi/iscsid.conf
        systemctl restart iscsid open-iscsi
        iscsiadm -m discovery -t sendtargets -p 192.168.1.70
        iscsiadm -m node --login -p 192.168.1.70
        SHELL

      end
      
      # iscsiターゲット (サーバー)
      if host == "target" then
        config.vm.provider :virtualbox do |p|
          vdisk = "vdisk.vdi"
          # iscsi device 4Gi
          if not File.exist?(vdisk) then
            p.customize [
              'createmedium', 'disk',
              '--filename', vdisk,
              '--format', 'VDI',
              '--size', 4096]
          end

          p.customize [
            'storageattach', :id,
            '--storagectl', 'SCSI',
            '--port', 2,
            '--device', 0,
            '--type', 'hdd',
            '--medium', vdisk]
        end
        
        
        config.vm.provision "shell", inline: <<-SHELL
        apt-get update
        apt-get install -y iscsitarget iscsitarget-dkms
        sed 's/^ISCSITARGET_ENABLE=false/ISCSITARGET_ENABLE=true/' -i /etc/default/iscsitarget
        cat >> /etc/iet/ietd.conf <<EOF
Target iqn.2016-04.world.srv:target00
  Lun 0 Path=/dev/sdc,Type=fileio
  incominguser username password 
EOF
        mkfs.ext4 -q /dev/sdc
        systemctl restart iscsitarget
        SHELL
      end
    end
  end
end

Vagrantfileの実行内容の要約

iSCSIの設定は、今回の目的では無いので、詳しい説明は省略しますが、実行する内容を以下に箇条書きにします。

  • 192.168.1.70 の IPアドレスで、iSCSIターゲットとなる仮想サーバーを起動する
  • ターゲットの仮想サーバーには、iSCSIとして提供するボリュームを vdisk.vdi として4GBの容量を確保する
  • 192.168.1.71 の IPアドレスで、イニシエータと持つ仮想サーバーを作成する
  • イニシエータの仮想サーバーは、ターゲットのボリュームを接続して、マウントできる状態で起動する

iSCSIサーバーの起動

上記のVagrantfileを置いた場所で、vagrant status を実行して、Vagrantfileが認識されることを確認します。

imac:k8s-pv-iscsi maho$ vagrant status
Current machine states:

target                    not created (virtualbox)
initiator                 not created (virtualbox)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

次に、vagrant up を実行することで、iSCSIターゲット(サーバー) と iSCSIイニシエータ(クライアント)が起動します。

imac:k8s-pv-iscsi maho$ vagrant up
Bringing machine 'target' up with 'virtualbox' provider...
Bringing machine 'initiator' up with 'virtualbox' provider...
==> target: Importing base box 'ubuntu/xenial64'...
省略
    initiator: Logging in to [iface: default, target: iqn.2016-04.world.srv:target00, portal: 192.168.1.70,3260] (multiple)
    initiator: Login to [iface: default, target: iqn.2016-04.world.srv:target00, portal: 192.168.1.70,3260] successful.

iSCSIサーバーの稼働確認

vagrant status を実行することで、下記の様に起動を確認することができます。

imac:k8s-pv-iscsi maho$ vagrant status
Current machine states:

target                    running (virtualbox)
initiator                 running (virtualbox)
省略

一つのVagrantfileから、二つの仮想サーバーが起動しています。 次の様にvagrant ssh サーバー名 でログインしたいサーバー名を指定することで、目的の仮想サーバーにログインします。 ここでは、iSCSIのボリュームをアタッチするクライアント側のサーバーにログインします。
root権限で、fdisk -lを実行することで、iSCSIで接続されたボリュームと内臓ボリュームを一度にリストすることができます。
mount -t ext4 /dev/sdc /mntによって、ファイルシステムのマウントできる事を確認しておきます。

imac:k8s-pv-iscsi maho$ vagrant ssh initiator
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-119-generic x86_64)
省略
vagrant@initiator:~$ 
vagrant@initiator:~$ sudo fdisk -l
Disk /dev/sda: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x334a7b8f

Device     Boot Start      End  Sectors Size Id Type
/dev/sda1  *     2048 20971486 20969439  10G 83 Linux


Disk /dev/sdb: 10 MiB, 10485760 bytes, 20480 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/sdc: 4 GiB, 4294967296 bytes, 8388608 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

vagrant@initiator:~$ sudo mount -t ext4 /dev/sdc /mnt
vagrant@initiator:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            238M     0  238M   0% /dev
tmpfs            49M  1.9M   47M   4% /run
/dev/sda1       9.7G  1.1G  8.7G  11% /
tmpfs           245M     0  245M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           245M     0  245M   0% /sys/fs/cgroup
tmpfs            49M     0   49M   0% /run/user/1000
vagrant         931G  506G  425G  55% /vagrant
/dev/sdc        3.9G  8.0M  3.6G   1% /mnt

vagrant@initiator:~$ ls -al /mnt
total 24
drwxr-xr-x  3 root root  4096 Apr 22 12:29 .
drwxr-xr-x 24 root root  4096 Apr 22 12:30 ..
drwx------  2 root root 16384 Apr 22 12:29 lost+found

マウントした状態で、iSCSIのボリュームに cd で移動して、MySQLが、テーブルスペースとして利用するディレクトリを `mkdir /mnt/mysql-data' として作成して、モードを変更して、MySQLのコンテナがアクセスできる様にしておきます。

vagrant@initiator:~$ sudo mkdir /mnt/mysql-data
vagrant@initiator:~$ sudo chmod 0777 /mnt/mysql-data
vagrant@initiator:~$ ls -al /mnt
total 28
drwxr-xr-x  4 root root  4096 Apr 22 12:40 .
drwxr-xr-x 24 root root  4096 Apr 22 12:30 ..
drwx------  2 root root 16384 Apr 22 12:29 lost+found
drwxrwxrwx  2 root root  4096 Apr 22 12:40 mysql-data

umount /mntでアンマウントしてから、iscsiadm -m node --logout でiSCSIもログアウトして、接続を解除します。

vagrant@initiator:~$ sudo umount /mnt
vagrant@initiator:~$ sudo iscsiadm -m node --logout
Logging out of session [sid: 1, target: iqn.2016-04.world.srv:target00, portal: 192.168.1.70,3260]
Logout of [sid: 1, target: iqn.2016-04.world.srv:target00, portal: 192.168.1.70,3260] successful.

以上で、iSCSIのターゲットとマウントするべきボリュームの準備が完了しました。

Secretの作成

ここから、k8sに必要な設定を実施していきます。 MySQLのコンテナが動作するポッドは、iSCSIターゲットに、ユーザーIDとパスワードで認証を通過して、ログインする必要があります。 一方で、k8sには、ユーザーIDやパスワードなどのセンシティブな情報を日常的に操作するオペレータや開発者から見えない様する secretという機能があります。
そこで、iSCSIのユーザーIDとパスワードをシークレットに保存します。 ポッドが利用する場合には、metadata.nameの値フィールドの chap-secretを指定することで、利用できる様になります。

chap-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: chap-secret
type: "kubernetes.io/iscsi-chap"  
data:
  node.session.auth.username: dXNlcm5hbWUK
  node.session.auth.password: cGFzc3dvcmQK

ユーザー名とパスワードのbase64エンコード

ここで注意点が、ユーザIDとパスワードの文字列は、base64でエンコードしておく必要があります。 次の例では、MacOSのコマンドで、ユーザーIDの'username'とpassword をbase64でエンコードする例です。 usernameとpasswordは、実際のシステムに適用する場合には、推定されない値を利用してくださいね。 変換された文字列をコピペで、chap-secret.yamlに貼り付けて、編集を終えます。

imac:k8s-pv-iscsi maho$ echo username |base64
dXNlcm5hbWUK
imac:k8s-pv-iscsi maho$ echo password |base64
cGFzc3dvcmQK

secretの作成

次に、上記で作成したYAMLファイルをkubectl apply -f YAMLファイル名で、k8sクラスタへ保存します。 そして、kubectl get secretsで保存された事を確認することできます。

vagrant@k8s1:/vagrant/yaml$ kubectl apply -f chap-secret.yaml 
secret "chap-secret" created

vagrant@k8s1:/vagrant/yaml$ kubectl get secrets
NAME                  TYPE                                  DATA      AGE
chap-secret           kubernetes.io/iscsi-chap              2         2s

ポッドからiSCSIディスクのマウント

MySQLのコンテナをデプロイする前に、iSCSIで接続するだけの、ポッドを作成して、接続できる事を確認します。
このYAMLファイルで実現する事を以下に箇条書きで列挙しておきます。

  • ubuntuコンテナを利用
  • iscsiボリュームを/mntにマウントする。 subPathを指定して mysql-data を /mnt へマウント
  • sleep 3600を実行して、コンテナが即時終了しない様に、1時間ほど待機させる
  • Volumes 以下の設置で、iSCSIへ接続する。 (PVやPVCを利用せず、ポッドから直接接続する点に注目)
  • secretRedで、ユーザーIDとパスワードを参照させる
ubuntu-pod-iscsi.yaml
apiVersion: v1
kind: Pod
metadata:
  name: ubuntu-initiator
spec:
  containers:
  - name: mysql
    image: ubuntu:latest
    volumeMounts:
    - mountPath: /mnt
      name: iscsivol
      subPath: mysql-data
    command: ["sleep","3600"]	  
  volumes:
  - name: iscsivol
    iscsi:
      targetPortal: 192.168.1.70
      iqn: iqn.2016-04.world.srv:target00
      lun: 0
      fsType: ext4
      readOnly: true
      chapAuthDiscovery: true
      chapAuthSession: true
      secretRef: 
        name: chap-secret

ここで作成したYAMLファイルを適用して、ポッドを作成します。

vagrant@k8s1:/vagrant/yaml$ kubectl apply -f ubuntu-pod-iscsi.yaml
pod "ubuntu-initiator" created

実行を確認するために、kubelet get podsで確認します。

vagrant@k8s1:/vagrant/yaml$ kubectl get pods
NAME                               READY     STATUS    RESTARTS   AGE
ubuntu-initiator                   1/1       Running   0          1m

このポッドで、対話型でシェルを動作させて、ログインした様にします。そして、/mntにiSCSIのボリュームがマウントされている事を確認します。

vagrant@k8s1:/vagrant/yaml$ kubectl exec -it ubuntu-initiator bash
root@ubuntu-initiator:/# df -h
Filesystem      Size  Used Avail Use% Mounted on
none            9.7G  2.6G  7.2G  27% /
tmpfs          1001M     0 1001M   0% /dev
tmpfs          1001M     0 1001M   0% /sys/fs/cgroup
/dev/sdc        3.9G  8.0M  3.6G   1% /mnt
/dev/sda1       9.7G  2.6G  7.2G  27% /etc/hosts
shm              64M     0   64M   0% /dev/shm
tmpfs          1001M   12K 1001M   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs          1001M     0 1001M   0% /sys/firmware

root@ubuntu-initiator:/# ls -al /mnt
total 8
drwsrwxrwx  2 root root 4096 Apr 22 12:40 .
drwxr-xr-x 35 root root 4096 Apr 22 13:03 ..

もし、ここでPODが実行できない場合、k8sクラスタのノードの仮想サーバーに、open-iscsi のパッケージが、インストールされている事を確認してください。 コンテナは、ホストになっているカーネルを利用して、名前空間の異なるプロセスとして実行しているために、ホスト側のカーネルにiSCSIの機能拡張が無い場合、コンテナがiSCSIを利用できないためです。

# apt-get update
# apt-get install -y open-iscsi

これで、確認用のポッドが動作したら、MySQLを実行します。
その前に、クリーンナップとして、以下を実行して、ポッドを停止しておきます。

vagrant@k8s1:/vagrant/yaml$ kubectl delete -f ubuntu-pod-iscsi.yaml

MySQLサーバーの起動

これから、MySQLサーバーを起動するためのYAMLファイルを準備します。 MySQLの公式コンテナには、環境変数によるAPIが準備されており、パスワードやデータベースを設定する事ができます。 前回同様にYAMLファイルで実現するポイントを箇条書きにします。

  • kindDeployment を指定します。 このデプロイメント・コントローラの機能によって、k8sクラスタ上で常にreplicasの数だけ、ポッドが起動する様になります。 これによって、MySQLコンテナが稼働するワーカーノードが、停止した際に、他の健全なワーカーノードにMySQLを起動してくれます。
  • マウントポイントは、/var/lin/mysqlとして、公式MySQLコンテナのAPI仕様に従って指定します。
  • MySQLサーバーのポート番号として、3306を公開します。
  • iSCSIのボリュームの設定部分は、前述の接続テスト用の設定と同字ですが、一箇所、readOnly:のフィールドをfalseに変更します。もし、この変更を忘れると、MySQLがボリュームを初期化できずに、ポッドが再起動を繰り返す事になるので注意です。
mysql-deploy-iscsi.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: mysql-server
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql-server
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_DATABASE
          value: test
        - name: MYSQL_ROOT_PASSWORD
          value: root
        - name: MYSQL_USER
          value: dev
        - name: MYSQL_PASSWORD
          value: dev
        volumeMounts:
        - mountPath: /var/lib/mysql
          name: iscsivol
          subPath: mysql-data
      volumes:
      - name: iscsivol
        iscsi:
          targetPortal: 192.168.1.70
          iqn: iqn.2016-04.world.srv:target00
          lun: 0
          fsType: ext4
          readOnly: false
          chapAuthDiscovery: true
          chapAuthSession: true
          secretRef: 
            name: chap-secret

ISCSIダーゲットのIPアドレスを直書きしていますので、kube-dnsを利用してIPアドレスを解決する方法は、後日、補足したいと思います。

上記で作成したYAMLファイルを適応して、デプロイします。

vagrant@k8s1:/vagrant/yaml$ kubectl apply -f mysql-deploy-iscsi.yaml
deployment.extensions "mysql-server" created

次のコマンドで、確認することができます。 IPはポッドのIPアドレス、NODEはデプロイされたワーカーノードになります。

vagrant@k8s1:/vagrant/yaml$ kubectl get pods -o wide
NAME                               READY     STATUS    RESTARTS   AGE       IP            NODE
mysql-server-68b5dfdf4d-2wb67      1/1       Running   0          54s       10.244.1.88   k8s2

kubectl exec -it mysql-server-68b5dfdf4d-2wb67 bash でポッド名を指定して、MySQLのコンテナと対話的にコマンド実行することができます。 iSCSIデバイスの/dev/sdc/var/lib/mysqlにマウントされている事が確認できます。

vagrant@k8s1:/vagrant/yaml$ kubectl exec -it mysql-server-68b5dfdf4d-2wb67 bash
root@mysql-server-68b5dfdf4d-2wb67:/# df
Filesystem     1K-blocks    Used Available Use% Mounted on
none            10098468 2657036   7425048  27% /
tmpfs            1024024       0   1024024   0% /dev
tmpfs            1024024       0   1024024   0% /sys/fs/cgroup
/dev/sda1       10098468 2657036   7425048  27% /etc/hosts
shm                65536       0     65536   0% /dev/shm
/dev/sdc         3997376  223192   3548088   6% /var/lib/mysql
tmpfs            1024024      12   1024012   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs            1024024       0   1024024   0% /sys/firmware

MySQLの公式コンテナでは、空のテーブルスペース領域が与えられると、初期化処理を実行します。 /var/lib/mysqlをリストすると、次の様に初期化が完了していることが解ります。

root@mysql-server-68b5dfdf4d-2wb67:/# ls -al /var/lib/mysql
total 188488
drwsrwxrwx  6 mysql mysql     4096 Apr 22 13:15 .
drwxr-xr-x 19 root  root      4096 Apr 20 08:47 ..
-rw-r-----  1 mysql mysql       56 Apr 22 13:14 auto.cnf
-rw-------  1 mysql mysql     1675 Apr 22 13:14 ca-key.pem
-rw-r--r--  1 mysql mysql     1107 Apr 22 13:14 ca.pem
-rw-r--r--  1 mysql mysql     1107 Apr 22 13:14 client-cert.pem
-rw-------  1 mysql mysql     1679 Apr 22 13:14 client-key.pem
-rw-r-----  1 mysql mysql     1341 Apr 22 13:14 ib_buffer_pool
-rw-r-----  1 mysql mysql 50331648 Apr 22 13:15 ib_logfile0
-rw-r-----  1 mysql mysql 50331648 Apr 22 13:14 ib_logfile1
-rw-r-----  1 mysql mysql 79691776 Apr 22 13:15 ibdata1
-rw-r-----  1 mysql mysql 12582912 Apr 22 13:15 ibtmp1
drwxr-x---  2 mysql mysql     4096 Apr 22 13:14 mysql
drwxr-x---  2 mysql mysql     4096 Apr 22 13:14 performance_schema
-rw-------  1 mysql mysql     1679 Apr 22 13:14 private_key.pem
-rw-r--r--  1 mysql mysql      451 Apr 22 13:14 public_key.pem
-rw-r--r--  1 mysql mysql     1107 Apr 22 13:14 server-cert.pem
-rw-------  1 mysql mysql     1679 Apr 22 13:14 server-key.pem
drwxr-x---  2 mysql mysql    12288 Apr 22 13:14 sys
drwxr-x---  2 mysql mysql     4096 Apr 22 13:14 test
root@mysql-server-68b5dfdf4d-2wb67:/# 

サービスの作成

k8sクラスタ内のアプリケーションに対して、コンテナをホストするノードが変わっても一定のIPアドレスでアクセスできる様に、サービスを設定して、クラスタIPを取得します。それと同時に、ノードのIPアドレス上のポート番号を通じてk8sクラスタの外部からアクセスできる様にNodePortを利用します。 NodePortは、ノードにポートを開くと同時に、クラスタIPを獲得することができます。

mysql-service.yaml
mysql-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  type: NodePort
  selector:
    app: mysql-server
  ports:
  - protocol: TCP
    port: 3306
    nodePort: 32306

上記のYAMLファイルを適応して、サービスを作成後、確認します。 以下の確認結果では、k8sクラスタ内にサービスIPアドレスは、ポッドネットワーク上の10.244.120.7 であること、そして、ノードポート 32306 で、MySQLサーバーのアクセスを受け付けることがわかります。

vagrant@k8s1:/vagrant/yaml$ kubectl apply -f mysql-service.yaml
service "mysql" created

vagrant@k8s1:/vagrant/yaml$ kubectl get svc
NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
省略
mysql                      NodePort    10.244.120.7     <none>        3306:32306/TCP   7s

MySQLサーバーへのアクセス

MySQLサーバーにアクセスして、動作確認を進めていきます。

k8sクラスタ内からのアクセス

k8sクラスタ内に対話でシェルやコマンドが使えるデプロイメントを起動します。

vagrant@k8s1:/vagrant/yaml$ kubectl run ubuntu --image=ubuntu:latest -- tail -f /dev/null
deployment.apps "ubuntu" created

デプロイメントのポッド名を確認して、対話シェルを起動します。 そして、mysql-clientをインストールします。

vagrant@k8s1:/vagrant/yaml$ kubectl get pods
NAME                               READY     STATUS    RESTARTS   AGE
ubuntu-fcdb8ff7-4dkvb              1/1       Running   0          11s

vagrant@k8s1:/vagrant/yaml$ kubectl exec -it ubuntu-fcdb8ff7-4dkvb bash
root@ubuntu-fcdb8ff7-4dkvb:/# apt-get update
Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB]
省略
root@ubuntu-fcdb8ff7-4dkvb:/# apt-get install mysql-client -y

サービス名は、kube-dnsに登録されていますから、mysql -h mysql -u root -prootで、DNS名でアクセスすることができます。

root@ubuntu-fcdb8ff7-4dkvb:/# mysql -h mysql -u root -proot 
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.22 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
5 rows in set (0.00 sec)

mysql> 

k8sクラスタのポッドから、mysqlのVIP相当のIPアドレスにアクセスすることができました。

クラスタ外からのアクセス

次に、ノードのポート番号に対して、アクセスを確認します。 マスターノードにも kube-proxyが動作していますから、マスターノードのIPアドレスとNodePortで指定したポート番号に、MySQLクライアントで接続できる事を確認します。

imac:yaml maho$ mysql -u root -proot -h 192.168.1.91 -P 32306
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.22 MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
5 rows in set (0.00 sec)

ノード障害時の計画的な退避

ポッドをホストするノードに何らかの障害が発生してケースを想定して、現在ポッドが動作しているノードから、他のノードへポッドを退避させる動作を見てみます。 まず、現在のノードを調べます。

vagrant@k8s1:/vagrant/yaml$ kubectl get pods -o wide
NAME                               READY     STATUS    RESTARTS   AGE       IP            NODE
mysql-server-68b5dfdf4d-jd2fn      1/1       Running   0          7m        10.244.1.98   k8s2
省略

ワーカノード k8s2上のポッドを他のポッドに退避させるために、kubectl drain k8s2 --ignore-daemonsetsを実行します。
以下の結果から、48秒で退避(テイクオーバー)が完了したことが判ります。

vagrant@k8s1:/vagrant/yaml$ date
Sun Apr 22 13:43:59 UTC 2018

vagrant@k8s1:/vagrant/yaml$ kubectl drain k8s2 --ignore-daemonsets
node "k8s2" cordoned
WARNING: Ignoring DaemonSet-managed pods: kube-flannel-ds-5lsd4, kube-proxy-n82vs
省略
pod "mysql-server-68b5dfdf4d-jd2fn" evicted
省略
node "k8s2" drained

vagrant@k8s1:/vagrant/yaml$ date
Sun Apr 22 13:44:47 UTC 2018

退避先のノードを確認しておきます。

vagrant@k8s1:/vagrant/yaml$ kubectl get pods -o wide
NAME                               READY     STATUS    RESTARTS   AGE       IP            NODE
省略
mysql-server-68b5dfdf4d-jlgj2      1/1       Running   0          1m        10.244.2.88   k8s3
省略

k8s2に、ポッドにスケジュールされる様に、状態を変更しておきます。

vagrant@k8s1:/vagrant/yaml$ kubectl uncordon k8s2
node "k8s2" uncordoned

突然のノード停止時の動作

次に、ハードウェア障害などで、突然停止したケースを想定したテストを実施します。 $ vagrant halt k8s3 を実行して、直後に、次のdateコマンドを実行しました。 この状態ではk8sは障害を検知していません。

vagrant@k8s1:/vagrant/yaml$ date
Sun Apr 22 13:48:29 UTC 2018
vagrant@k8s1:/vagrant/yaml$ kubectl get pods -o wide
NAME                               READY     STATUS    RESTARTS   AGE       IP            NODE
mysql-server-68b5dfdf4d-jlgj2      1/1       Running   0          4m        10.244.2.88   k8s3
省略

vagrant@k8s1:/vagrant/yaml$ kubectl get deploy -o wide
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE       CONTAINERS        IMAGES           SELECTOR
mysql-server      1         1         1            1           34m       mysql             mysql:5.7        app=mysql-server
省略

約30秒後に、AVAILABLE = 0となり、停止を検知しています。

vagrant@k8s1:/vagrant/yaml$ date
Sun Apr 22 13:49:08 UTC 2018
vagrant@k8s1:/vagrant/yaml$ kubectl get deploy -o wide
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE       CONTAINERS        IMAGES           SELECTOR
mysql-server      1         1         1            0           34m       mysql             mysql:5.7        app=mysql-server
省略

それから、約5分後に、ワーカーノードk8s2で mysqlサーバーのポッドが立ち上がり、フェイルオーバーが完了したことが判ります。

vagrant@k8s1:/vagrant/yaml$ date
Sun Apr 22 13:53:54 UTC 2018

vagrant@k8s1:/vagrant/yaml$ kubectl get pods -o wide
NAME                               READY     STATUS    RESTARTS   AGE       IP             NODE
mysql-server-68b5dfdf4d-7j642      1/1       Running   0          27s       10.244.1.108   k8s2
mysql-server-68b5dfdf4d-jlgj2      1/1       Unknown   0          9m        10.244.2.88    k8s3

まとめ

k8sクラスタのポッドから、iSCSIターゲットのボリュームを利用できること、iSCSIはポッドとボリュームが一対一接続のために、PVやPVCを利用することなく、ポッドに設定してボリュームをアクセスできることが確認できました。 さらに、サービスを利用することで、ノード障害時にも、アプリケーションはVIP相当のクラスタIPのDNS名でアクセスを続けられることが確認できました。

ポッドが健全なノードで起動するまでには、約5分間の猶予時間が設定されていて、テスト中は長いと感じます。 しかし、敏感に反応してしまうと、例えば重い処理が実行されているケースに、意図しないフェールオーバーが起動して、障害となるケースを考慮すると、5分程度の適度な猶予時間を持つことは、適切な動きと思います。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?