1,000ノードクラスタの負荷状況

多数のノードが含まれるクラスタでの負荷状況を確認するため、aws の環境を使って、1,000ノードのTungstenFabricクラスタを試してみている。

台数が多く、ansible-deployer だと構築に時間がかかったため、今回は以下のリンク先に従って、 kube-manager, vRouter のモジュールについては、kubernetes の機能を使って配布するようにした。
https://github.com/Juniper/contrail-ansible-deployer/wiki/Provision-Contrail-Kubernetes-Cluster-in-Non-nested-Mode

AMIについては、引き続き CentOS7.5 (ami-3185744e) を使用し、インスタンスタイプは、TungstenFabric controller, k8s master については、m3.xlarge (4vCPU, 16GB mem) 各1台, k8s node については、m3.medium (1vCPU, 4GB mem) 1,000台、を使用している。

1. TungstenFabric controller の構築

以下のリンクと同様、 ansible-deployer でインストールを行う。
http://aaabbb-200904.hatenablog.jp/entry/2019/02/10/222958

instance.yaml は、以下のように、controller 1台だけを指定している。(k8s_master, kube-managerは削除)

provider_config:
  bms:
   ssh_user: root
   ssh_public_key: /root/.ssh/id_rsa.pub
   ssh_private_key: /root/.ssh/id_rsa
   domainsuffix: local
   ntpserver: ntp.nict.jp
instances:
  bms1:
   provider: bms
   roles:
      config_database:
      config:
      control:
      analytics:
      webui:
   ip: 172.31.xx.xx
contrail_configuration:
  CONTAINER_REGISTRY: opencontrailnightly
  CONTRAIL_VERSION: latest
  KUBERNETES_CLUSTER_PROJECT: {}
  JVM_EXTRA_OPTS: "-Xms128m -Xmx1g"
global_configuration:

2. k8s master の構築

以下のリンクに従い、kubeadm を使った k8s master の構築を実施している。
https://github.com/Juniper/contrail-docker/wiki/Provision-Contrail-CNI-for-Kubernetes#faqs

# cd
# cat install-k8s-packages.sh
bash -c 'cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
     https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF'
setenforce 0
yum install -y kubelet kubeadm kubectl docker
systemctl enable docker && systemctl start docker
systemctl enable kubelet && systemctl start kubelet
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
swapoff -a

# bash install-k8s-packages.sh

# kubeadm init
※ 以下のようなコマンドが表示されるのでひかえておく
kubeadm join 172.31.18.113:6443 --token we70in.mvy0yu0hnxb6kxip --discovery-token-ca-cert-hash sha256:13cf52534ab14ee1f4dc561de746e95bc7684f2a0355cb82eebdbd5b1e9f3634

# mkdir -p $HOME/.kube
# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# chown $(id -u):$(id -g) $HOME/.kube/config

3. k8s node の構築

上記のスクリプトk8s node でも実行し、その後、 kubeadm join を実施する必要がある。
並列で処理を実行するため、今回は GNU parallel と ssh を使用した。

まず、aws 内のノードについて、private ip の一覧を取得する。 (TungstenFabric controller, k8s master の ip は手動で削っておく)

$ pip install awscli
$ aws configure
 (access key, secret key, region 等を入力 (必要に応じて、 IAM から作成))
$ aws ec2 describe-instances --query 'Reservations[*].Instances[*].PrivateIpAddress' --output text | tr '\t' '\n' > /tmp/aaa.txt

その後、上記のリストを k8s master のインスタンスに送り、以下のようなコマンドで k8s node での実行を行う。(/tmp/aaa.pem は、EC2 インスタンス立ち上げ時に指定した pem ファイル)
※ 10-15分程度で完了した

yum -y install epel-release 
yum -y install parallel
ulimit -n 4096
cat aaa.txt | parallel -j1000 scp -i /tmp/aaa.pem -o StrictHostKeyChecking=no install-k8s-packages.sh centos@{}:/tmp
cat aaa.txt | parallel -j1000 ssh -i /tmp/aaa.pem -o StrictHostKeyChecking=no centos@{} chmod 755 /tmp/install-k8s-packages.sh
cat aaa.txt | parallel -j1000 ssh -i /tmp/aaa.pem -o StrictHostKeyChecking=no centos@{} sudo /tmp/install-k8s-packages.sh
cat aaa.txt | parallel -j1000 ssh -i /tmp/aaa.pem -o StrictHostKeyChecking=no centos@{} sudo kubeadm join 172.31.18.113:6443 --token we70in.mvy0yu0hnxb6kxip --discovery-token-ca-cert-hash sha256:13cf52534ab14ee1f4dc561de746e95bc7684f2a0355cb82eebdbd5b1e9f3634

4. vRouter の展開

上記が完了した後、 k8s master 上で以下を発行し、vRouter の展開を行う。(余分なコストがかかるのを防ぐため、kubectl apply 直前までは、k8s node を立ち上げる前に実施した方がよいかもしれない)

# cd
# yum -y install git
# git clone https://github.com/Juniper/contrail-container-builder.git
# cd /root/contrail-container-builder/kubernetes/manifests
# vi ../../common.env
(以下を追記)
CONTRAIL_CONTAINER_TAG=latest
CONTRAIL_REGISTRY=opencontrailnightly

# ./resolve-manifest.sh contrail-non-nested-kubernetes.yaml > cni-vrouter.yaml 
※ 手動で以下の修正を行う (1. Null になってしまう行を削除, 2. k8s master の ip が入ってしまう部分の一部を TungstenFabric controller の ip で置き換え)
--- cni-vrouter.yaml.orig	2019-03-17 21:17:25.218399040 +0900
+++ cni-vrouter.yaml	2019-03-17 21:19:40.744368162 +0900
@@ -11,36 +11,20 @@
   namespace: kube-system
 data:
   AUTH_MODE: {{ AUTH_MODE }}
-  KEYSTONE_AUTH_HOST: {{ KEYSTONE_AUTH_HOST }}
-  KEYSTONE_AUTH_ADMIN_TENANT: "{{ KEYSTONE_AUTH_ADMIN_TENANT }}"
-  KEYSTONE_AUTH_ADMIN_USER: "{{ KEYSTONE_AUTH_ADMIN_USER }}"
-  KEYSTONE_AUTH_ADMIN_PASSWORD: "{{ KEYSTONE_AUTH_ADMIN_PASSWORD }}"
-  KEYSTONE_AUTH_ADMIN_PORT: "{{ KEYSTONE_AUTH_ADMIN_PORT }}"
-  KEYSTONE_AUTH_URL_VERSION: "{{ KEYSTONE_AUTH_URL_VERSION }}"
-  ANALYTICS_API_VIP: {{ ANALYTICS_API_VIP }}
-  ANALYTICS_NODES: {{ ANALYTICS_NODES }}
-  ANALYTICSDB_NODES: {{ ANALYTICSDB_NODES }}
+  ANALYTICS_NODES: TungstenFabric controller IP
+  ANALYTICSDB_NODES: TungstenFabric controller IP
   CLOUD_ORCHESTRATOR: {{ CLOUD_ORCHESTRATOR }}
-  CONFIG_API_VIP: {{ CONFIG_API_VIP }}
-  CONFIG_NODES: {{ CONFIG_NODES }}
-  CONFIGDB_NODES: {{ CONFIGDB_NODES }}
-  CONTROL_NODES: {{ CONTROL_NODES }}
-  CONTROLLER_NODES: {{ CONTROLLER_NODES }}
+  CONFIG_NODES: TungstenFabric controller IP
+  CONFIGDB_NODES: TungstenFabric controller IP
+  CONTROL_NODES: TungstenFabric controller IP
+  CONTROLLER_NODES: TungstenFabric controller IP
   LOG_LEVEL: {{ LOG_LEVEL }}
   METADATA_PROXY_SECRET: {{ METADATA_PROXY_SECRET }}
-  RABBITMQ_NODES: {{ RABBITMQ_NODES }}
+  RABBITMQ_NODES: TungstenFabric controller IP
   RABBITMQ_NODE_PORT: "{{ RABBITMQ_NODE_PORT }}"
-  ZOOKEEPER_NODES: {{ ZOOKEEPER_NODES }}
+  ZOOKEEPER_NODES: TungstenFabric controller IP
   ZOOKEEPER_PORTS: "{{ ZOOKEEPER_PORTS }}"
   ZOOKEEPER_PORT: "{{ ZOOKEEPER_PORT }}"
-  KUBERNETES_CLUSTER_NETWORK: "{{ KUBERNETES_CLUSTER_NETWORK }}"
-  KUBERNETES_CLUSTER_NAME: {{ KUBERNETES_CLUSTER_NAME }}
-  KUBERNETES_POD_SUBNETS: {{ KUBERNETES_POD_SUBNETS }}
-  KUBERNETES_IP_FABRIC_SUBNETS: {{ KUBERNETES_IP_FABRIC_SUBNETS }}
-  KUBERNETES_SERVICE_SUBNETS: {{ KUBERNETES_SERVICE_SUBNETS }}
-  KUBERNETES_IP_FABRIC_FORWARDING: "{{ KUBERNETES_IP_FABRIC_FORWARDING }}"
-  KUBERNETES_IP_FABRIC_SNAT: "{{ KUBERNETES_IP_FABRIC_SNAT }}"
-  KUBERNETES_PUBLIC_FIP_POOL: "{{ KUBERNETES_PUBLIC_FIP_POOL }}"
 ---
 apiVersion: v1
 kind: ConfigMap

# kubectl apply -f cni-vrouter.yaml

うまく適用されると、以下のように、1,000台の vRouter がクラスタに追加されるはずである。
f:id:aaabbb_200904:20190317221631p:plain

クラスタの状態

クラスタが立ち上がってから、各ノードのリソースを見てみたところ、TungstenFabric controller, k8s master で、以下のように CPU 使用率が高い状況になっていた。
※ TungstenFabric controller では、contrail-collector, redis 等、analytics の負荷が高く、k8s master では kube-apiserver, etcd の負荷が高くなった。
安定して稼働させるには、リソースの追加割り当てや、controller/analytics のスケールアウトなど、追加の考慮が必要かもしれない。

TungstenFabric controller, analytics:

top - 12:13:59 up 43 min,  1 user,  load average: 5.77, 12.05, 7.24
Tasks: 153 total,   1 running, 152 sleeping,   0 stopped,   0 zombie
%Cpu(s): 22.0 us, 16.9 sy,  0.0 ni, 60.3 id,  0.0 wa,  0.0 hi,  0.7 si,  0.1 st
KiB Mem : 15233672 total,  7091360 free,  3899712 used,  4242600 buff/cache
KiB Swap:        0 total,        0 free,        0 used. 10779720 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                 
21165 root      20   0 1035220 333448  10996 S  48.2  2.2   3:26.06 contrail-collec                         
18891 root      20   0  906588 249180   7524 S  31.9  1.6   0:09.03 node                                    
12763 polkitd   20   0  243412 189736   1668 S  28.6  1.2   2:45.55 redis-server                            
19410 root      20   0 1375424 108644  12148 S  14.3  0.7   1:40.42 contrail-dns                            
18864 root      20   0  810588 165356   7196 S  13.0  1.1   0:05.14 node                                    
19448 root      20   0 2167860   1.0g  13732 S  10.6  7.0  10:04.95 contrail-contro                         
11985 root      20   0  776036  94764  35204 S   3.0  0.6   2:38.34 dockerd                                 
15803 root      20   0  248324  40180   5332 S   2.3  0.3   0:27.72 python   


k8s master:

top - 12:14:09 up 43 min,  1 user,  load average: 11.84, 12.30, 8.06
Tasks: 133 total,   1 running, 132 sleeping,   0 stopped,   0 zombie
%Cpu(s): 87.2 us,  6.6 sy,  0.1 ni,  3.5 id,  0.2 wa,  0.0 hi,  2.4 si,  0.0 st
KiB Mem : 15233672 total,  8167188 free,  4032788 used,  3033696 buff/cache
KiB Swap:        0 total,        0 free,        0 used. 10702748 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                                 
11583 root      20   0 2999520   2.7g  37840 S 309.3 18.6  38:35.47 kube-apiserver                                                                                                          
 5854 root      20   0   10.3g 520460 181348 S  47.5  3.4   1:50.44 etcd                                                                                                                    
18836 root      20   0  481984 350196  27724 S  17.6  2.3   0:19.61 kube-controller                                                                                                         
11211 root      20   0 1572404  74628  31760 S   3.7  0.5   0:52.85 kubelet                                                                                                                 
18460 root      20   0  209628 119648  13428 S   2.7  0.8   0:08.79 kube-scheduler                                                                                                          
10663 root      20   0 1280720  60912  16316 S   0.7  0.4   1:12.93 dockerd-current                                                                                                         
  377 root      20   0  145808  88372  87852 S   0.3  0.6   0:42.88 systemd-journal  

一方、メモリ, disk については、数台での小規模なクラスタと比べて、大きな違いは見られなかった。
※ analyticsdb を有効化している場合、こちらも大きくリソースを使う可能性が高いため注意

TungstenFabric controller, analytics:
[root@ip-172-31-13-135 ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:            14G        4.3G        6.1G         17M        4.1G        9.7G
Swap:            0B          0B          0B
[root@ip-172-31-13-135 ~]# 
[root@ip-172-31-13-135 ~]# 
[root@ip-172-31-13-135 ~]# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1       20G  4.3G   16G  22% /
[root@ip-172-31-13-135 ~]# 

k8s master:
[root@ip-172-31-18-113 ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:            14G        3.5G        7.9G        105M        3.2G         10G
Swap:            0B          0B          0B
[root@ip-172-31-18-113 ~]# 
[root@ip-172-31-18-113 ~]# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1       20G  3.6G   17G  18% /
[root@ip-172-31-18-113 ~]#