레이블이 IBM POWER인 게시물을 표시합니다. 모든 게시물 표시
레이블이 IBM POWER인 게시물을 표시합니다. 모든 게시물 표시

2019년 11월 13일 수요일

Redhat ppc64le 서버에서 logstash를 설치하고 구성하기


IBM POWER9 서버, 즉 ppc64le 아키텍처 기반의 Redhat 서버에 logstash를 설치하고 구성하는 것을 간단히 해보겠습니다. 

먼저, logstash는 java 기반이기 때문에, 그냥 x86_64용으로 elastic.co에서 제공되는 RPM 파일을 그냥 그대로 받아다 설치해서 쓰시면 됩니다.

[user607@p607-kvm1 ~]$ wget https://artifacts.elastic.co/downloads/logstash/logstash-7.4.2.rpm

[user607@p607-kvm1 ~]$ sudo rpm -Uvh logstash-7.4.2.rpm
warning: logstash-7.4.2.rpm: Header V4 RSA/SHA512 Signature, key ID d88e42b4: NOKEY
Verifying...                          ################################# [100%]
Preparing...                          ################################# [100%]
Updating / installing...
   1:logstash-1:7.4.2-1               ################################# [100%]
Using provided startup.options file: /etc/logstash/startup.options
OpenJDK 64-Bit Server VM warning: TieredCompilation is disabled in this release.
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/pleaserun-0.0.30/lib/pleaserun/platform/base.rb:112: warning: constant ::Fixnum is deprecated
Successfully created system startup script for Logstash


다만 이걸 그대로 수행해보시면 아래와 같이 "load error: ffi/ffi" error가 나는 것을 보실 수 있습니다.

[root@p607-kvm1 user607]# /usr/share/logstash/bin/logstash
Thread.exclusive is deprecated, use Thread::Mutex
WARNING: Could not find logstash.yml which is typically located in $LS_HOME/config or /etc/logstash. You can specify the path using --path.settings. Continuing using the defaults
Could not find log4j2 configuration at path /usr/share/logstash/config/log4j2.properties. Using default config which logs errors to the console
[INFO ] 2019-11-12 23:56:52.605 [main] writabledirectory - Creating directory {:setting=>"path.queue", :path=>"/usr/share/logstash/data/queue"}
[INFO ] 2019-11-12 23:56:52.633 [main] writabledirectory - Creating directory {:setting=>"path.dead_letter_queue", :path=>"/usr/share/logstash/data/dead_letter_queue"}
[ERROR] 2019-11-12 23:56:53.198 [LogStash::Runner] Logstash - java.lang.IllegalStateException: Logstash stopped processing because of an error: (LoadError) load error: ffi/ffi -- java.lang.NullPointerException: null


이는 https://github.com/elastic/logstash/issues/10755 에 기술된 bug 때문인데, 요약하면 jruby-complete-*.jar 파일 안의 powerpc64le-linux platform을 위한 directory에 실수로 platform.conf가 빠져 있기 때문에 발생하는 것입니다.  이는 아래와 같은 command로 간단히 확인하실 수 있습니다.   일단 아래와 같이 error가 나는지 확인하십시요.

[root@p607-kvm1 user607]# java -jar /usr/share/logstash/logstash-core/lib/jars/jruby-complete-9.2.8.0.jar -rffi -e 1
LoadError: load error: ffi/ffi -- java.lang.NullPointerException: null
  require at org/jruby/RubyKernel.java:987
  require at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:54
   <main> at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/ffi.rb:1
  require at org/jruby/RubyKernel.java:987
   (root) at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:1

확인되면 아래와 같이 powerpc64le-linux/types.conf 파일을 추출해내십시요.

[root@p607-kvm1 user607]# jar -xvf /usr/share/logstash/logstash-core/lib/jars/jruby-complete-9.2.8.0.jar META-INF/jruby.home/lib/ruby/stdlib/ffi/platform/powerpc64le-linux/types.conf
 inflated: META-INF/jruby.home/lib/ruby/stdlib/ffi/platform/powerpc64le-linux/types.conf

이 파일을 다음과 같이 powerpc64le-linux/platform.conf로 copy하십시요.

[root@p607-kvm1 user607]# cp META-INF/jruby.home/lib/ruby/stdlib/ffi/platform/powerpc64le-linux/types.conf META-INF/jruby.home/lib/ruby/stdlib/ffi/platform/powerpc64le-linux/platform.conf

이렇게 만들어진 powerpc64le-linux/platform.conf을 원래의 jruby-complete-*.jar 파일에 update하십시요.

[root@p607-kvm1 user607]# jar -uvf /usr/share/logstash/logstash-core/lib/jars/jruby-complete-9.2.8.0.jar META-INF/jruby.home/lib/ruby/stdlib/ffi/platform/powerpc64le-linux/platform.conf
adding: META-INF/jruby.home/lib/ruby/stdlib/ffi/platform/powerpc64le-linux/platform.conf(in = 3796) (out= 483)(deflated 87%)

이제 다시 테스트해보면 "load error: ffi/ffi"가 더 발생하지 않는 것을 보실 수 있습니다.

[root@p607-kvm1 user607]# java -jar /usr/share/logstash/logstash-core/lib/jars/jruby-complete-9.2.8.0.jar -rffi -e 1

[root@p607-kvm1 user607]# echo $?
0

이제 간단한 logstash config 파일을 작성합니다.  여기서는 /tmp/in.log에 뭔가 내용이 쌓이면 그걸 grok으로 filtering한 뒤 rubydebug codec으로 format하여 /tmp/out.log에 집어넣는 것입니다.

[root@p607-kvm1 user607]# vi logstash-simple.conf
input {
  file {
    path => "/tmp/in.log"
  }
}

filter {
  grok {
    match => { "message" => "%{NUMBER:timestamp} %{NUMBER:channel} %{MAC:client_mac} %{MAC:mac} %{INT:rssi}" }
 }
}

output {
  file {
    path => "/tmp/out.log"
}
  stdout { codec => rubydebug }
}

아래와 같이 logstash를 start 합니다.

[root@p607-kvm1 user607]# /usr/share/logstash/bin/logstash -f logstash-simple.conf
Thread.exclusive is deprecated, use Thread::Mutex
WARNING: Could not find logstash.yml which is typically located in $LS_HOME/config or /etc/logstash. You can specify the path using --path.settings. Continuing using the defaults
Could not find log4j2 configuration at path /usr/share/logstash/config/log4j2.properties. Using default config which logs errors to the console
[WARN ] 2019-11-13 00:23:47.244 [LogStash::Runner] multilocal - Ignoring the 'pipelines.yml' file because modules or command line options are specified
[INFO ] 2019-11-13 00:23:47.267 [LogStash::Runner] runner - Starting Logstash {"logstash.version"=>"7.4.2"}
[INFO ] 2019-11-13 00:23:50.305 [Converge PipelineAction::Create<main>] Reflections - Reflections took 75 ms to scan 1 urls, producing 20 keys and 40 values
[WARN ] 2019-11-13 00:23:52.059 [[main]-pipeline-manager] LazyDelegatingGauge - A gauge metric of an unknown type (org.jruby.RubyArray) has been create for key: cluster_uuids. This may result in invalid serialization.  It is recommended to log an issue to the responsible developer/development team.
[INFO ] 2019-11-13 00:23:52.065 [[main]-pipeline-manager] javapipeline - Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>16, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50, "pipeline.max_inflight"=>2000, :thread=>"#<Thread:0x370844ca run>"}
[INFO ] 2019-11-13 00:23:52.938 [[main]-pipeline-manager] file - No sincedb_path set, generating one based on the "path" setting {:sincedb_path=>"/usr/share/logstash/data/plugins/inputs/file/.sincedb_b3374bae0eefd65d5f3cdbcfd41ca004", :path=>["/tmp/in.log"]}
[INFO ] 2019-11-13 00:23:52.992 [[main]-pipeline-manager] javapipeline - Pipeline started {"pipeline.id"=>"main"}
[INFO ] 2019-11-13 00:23:53.081 [[main]<file] observingtail - START, creating Discoverer, Watch with file and sincedb collections
[INFO ] 2019-11-13 00:23:53.089 [Agent thread] agent - Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[INFO ] 2019-11-13 00:23:53.488 [Api Webserver] agent - Successfully started Logstash API endpoint {:port=>9600}


여기서 다음과 같이 일정 format의 string을 /tmp/in.log에 집어넣습니다.

[root@p607-kvm1 user607]#  echo "1524708231.794252221  8  c0:4a:00:40:e6:0e  c0:4a:00:40:AA:AA   -68" >> /tmp/in.log


그러면 logstash의 standard output log에 아래와 같이 그에 대한 처리가 되는 메시지가 나오는 것을 보실 수 있습니다.


[INFO ] 2019-11-13 00:24:54.175 [[main]>worker9] file - Opening file {:path=>"/tmp/out.log"}
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/awesome_print-1.7.0/lib/awesome_print/formatters/base_formatter.rb:31: warning: constant ::Fixnum is deprecated
{
    "@timestamp" => 2019-11-13T05:24:53.785Z,
          "path" => "/tmp/in.log",
      "@version" => "1",
          "host" => "p607-kvm1",
          "tags" => [
        [0] "_grokparsefailure"
    ],
       "message" => "1524708231.794252221  8  c0:4a:00:40:e6:0e  c0:4a:00:40:AA:AA   -68"
}
[INFO ] 2019-11-13 00:25:11.708 [[main]>worker9] file - Closing file /tmp/out.log


그리고 그 결과로 아래와 같이 format된 string이 지정된 file로 저장된 것을 보실 수 있습니다. 

[root@p607-kvm1 user607]# cat /tmp/out.log
{"@timestamp":"2019-11-13T05:24:53.785Z","path":"/tmp/in.log","@version":"1","host":"p607-kvm1","tags":["_grokparsefailure"],"message":"1524708231.794252221  8  c0:4a:00:40:e6:0e  c0:4a:00:40:AA:AA   -68"}

2019년 11월 4일 월요일

IBM POWER 가상머신에서의 RPS(Receive Packet Steering)을 이용한 network performance tuning


IBM Virtual Machine에서는 다음과 같이 RSS(Receive Side Scaling)가 receive (input) queue 1개로 제한됩니다.  아래는 POWER8 KVM 환경입니다.

[user607@p607-kvm2 ~]$ egrep 'CPU|virtio0' /proc/interrupts
           CPU0       CPU1       CPU2       CPU3       CPU4       CPU5       CPU6       CPU7       CPU8       CPU9       CPU10      CPU11      CPU12      CPU13      CPU14      CPU15
 47:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0      XICS 4126 Edge      virtio0-config
 48:         48          0          0          0          0          0          0          0          0   57548404          0          0          0          0          0          0      XICS 4127 Edge      virtio0-input.0
 49:          1          0          0          0          0          0          0       4414          0          0          0          0          0          0          0          0      XICS 4128 Edge      virtio0-output.0


이 queue의 interrupt를 어떤 CPU가 처리하는지는 아래와 같이 찾을 수도 있습니다.

[user607@p607-kvm2 ~]$ sudo find /sys/devices -name "*eth0*"
/sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0

[user607@p607-kvm2 ~]$ ls -l /sys/devices/pci0000:00/0000:00:01.0/msi_irqs
total 0
-r--r--r-- 1 root root 65536 Oct 31 22:47 47
-r--r--r-- 1 root root 65536 Oct 31 22:47 48
-r--r--r-- 1 root root 65536 Oct 31 22:47 49

virtio0-input.0, 즉 48번의 interrupt를 처리하는 CPU를 찾기 위해 /proc/irq/해당번호/smp_affinity 파일을 확인합니다.

[user607@p607-kvm2 ~]$ cat /proc/irq/48/smp_affinity
0200


위 숫자 string은 각 숫자 하나가 CPU 4개를 가리키는 16진수이며, 이를 2진수로 풀어놓으면 다음과 같습니다.   (16진수 2은 2^1이므로 2진수로는 0010 입니다)

(16진수) 0200
(2진수) 0000 0010 0000 0000 

각각의 2진수 숫자는 CPU 1개를 뜻하며, 뒤쪽부터 CPU0, CPU1, CPU2...를 표시합니다.  1로 표시된 CPU가 이 interrupt를 처리하는데 사용되는 CPU를 뜻합니다.
즉 총 16개의 CPU 중에서 (뒤쪽부터 셉니다) 10번째의 CPU가 이 interrupt를 처리한다는 뜻입니다.   맨 위에서 /proc/interrupts로 확인한 정보와 일치합니다.

이렇게 receive side queue가 1개 뿐이라면 혹시 heavy network traffic이 몰려들어올 때 해당 interrupt를 처리하는 CPU가 100% 차서 병목이 되는 일이 없을까요 ?   그 부분을 확인해보기 위해 network 부하 테스트 tool인 iperf를 설치하겠습니다.

[user607@p607-kvm2 ~]$ sudo yum groupinstall "Development Tools"

[user607@p607-kvm2 ~]$ wget https://iperf.fr/download/source/iperf-3.1.3-source.tar.gz

[user607@p607-kvm2 ~]$ tar -xf iperf-3.1.3-source.tar.gz

[user607@p607-kvm2 ~]$ cd iperf-3.1.3

[user607@p607-kvm2 iperf-3.1.3]$ ./configure

[user607@p607-kvm2 iperf-3.1.3]$ make -j8 && sudo make install

[user607@p607-kvm2 iperf-3.1.3]$ iperf3 -s -p 5021
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------

충분한 부하를 주기 위해, 이것 외에도 다음과 같이 5022~5024 port를 이용해 총 4개의 iperf3 server process를 구동해놓습니다.

[user607@p607-kvm2 iperf-3.1.3]$ iperf3 -s -p 5022
[user607@p607-kvm2 iperf-3.1.3]$ iperf3 -s -p 5023
[user607@p607-kvm2 iperf-3.1.3]$ iperf3 -s -p 5024


그리고 다른 서버에서 다음과 같이 이 4개 port에 대해 iperf3 client를 구동하여 작은 size의 packet들을 30초간 보냅니다.

user607@p607-kvm1:~$ user607@p607-kvm1:~$ for i in 1 2 3 4
> do
> iperf3 -c 129.40.252.107 -P 6 -t 30 -N -l 16 -p 502${i} &
> done

이렇게 해보면 다음과 같이 10번째 CPU가 정말 거의 95%에 달하는 것을 보실 수 있습니다.   다른 CPU들은 iperf3 server process들이 CPU를 100%씩 쓰고 있는 것입니다.




이 문제를 해결할 방법이 없을까요 ?  있습니다.  RPS(Receive Packet Steering)가 그것인데, 이는 쉽게 말해 RSS와 같은 것이지만 RSS가 HW적인 구현인 것에 비해 RPS는 SW적인 구현이라는 것입니다.  이건 기본적으로는 disable 처리되어 있습니다.  Disable 처리 여부는 다음과 같이 "...eth#/queues/rx-0/rps_cpus 파일에 할당된 CPU를 보고 확인하실 수 있습니다. 

[user607@p607-kvm2 ~]$ sudo find / -name queues
/sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues
/sys/devices/virtual/net/lo/queues

[user607@p607-kvm2 ~]$ ls -l /sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues/
total 0
drwxr-xr-x. 3 root root 0 Oct 29 18:57 rx-0
drwxr-xr-x. 3 root root 0 Oct 29 18:57 tx-0

[user607@p607-kvm2 ~]$ ls -l /sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues/rx-0
total 0
-rw-r--r--. 1 root root 65536 Oct 31 02:18 rps_cpus
-rw-r--r--. 1 root root 65536 Oct 31 02:18 rps_flow_cnt
drwxr-xr-x. 2 root root     0 Oct 29 18:58 virtio_net

[user607@p607-kvm2 ~]$ cat /sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues/rx-0/rps_cpus
0000

이렇게 0000이 들어있는 것은 disable되어 있다는 것입니다.   기본적으로 disable 처리가 된 것은 RSS로 multi-queue 처리가 된다면 굳이 RPS까지 함께 구현할 필요가 없기 떄문입니다.  그러나 Virtual 환경처럼 RSS에서 single-queue로만 처리가 되는 경우에는 도움이 될 수도 있습니다. 

RPS를 enable하기 위해서는 다음과 같이 그 처리를 해줄 CPU를 지정해주면 됩니다.

[root@p607-kvm2 user607]# echo "1001" > /sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues/rx-0/rps_cpus

[root@p607-kvm2 user607]# cat /sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues/rx-0/rps_cpus
1001

위와 같이 넣으면 16진수로 1001은 2진수로는 다음과 같이 표현됩니다. 

0001 0000 0000 0001

즉 전체 16개 CPU 중 첫번째 CPU와 13번째 CPU의 2개 CPU로 Receive packet들을 처리한다는 뜻입니다. 

이렇게 구성을 해놓고 위와 동일한게 4개 port에 대해 iperf3 server/client를 구동하여 작은 size의 packet들을 30초간 보냅니다.

user607@p607-kvm1:~$ user607@p607-kvm1:~$ for i in 1 2 3 4
> do
> iperf3 -c 129.40.252.107 -P 6 -t 30 -N -l 16 -p 502${i} &
> done

그 결과를 보면, 다음과 같이 RSS를 처리하는 10번 CPU의 사용률이 대폭 떨어지고, 대신 첫번째 CPU와 13번째 CPU의 사용률이 꽤 높이, 각각 약 35% 정도로 올라간 것을 보실 수 있습니다.





그리고 RSS만 이용했을 때와 RPS까지 함께 이용했을 때의 iperf 성능 결과는 아래와 같습니다.  4개 session을 사용했기 때문에 각각의 합을 비교했습니다.



보시는 바와 같이 network 처리 성능도 약~간 상승한 것을 보실 수 있습니다.  다만 이 가상머신 환경은 16개 CPU가 있기는 하지만 실제 물리적 CPU core는 2개 밖에 없고, 각 CPU core당 8개의 SMT(hyperthread)가 있는 것이라서, CPU 자원이 워낙 작습니다.  그런 상황에서 iperf server process도 CPU를 많이 사용하다보니, 정확한 성능 측정은 어려운 상황이라는 것은 감안하셔야 합니다.


RSS와 RPS에 대한 좀더 자세한 설명은 아래 URL을 참조하시기 바랍니다.

http://balodeamit.blogspot.com/2013/10/receive-side-scaling-and-receive-packet.html


IBM POWER (ppc64le) 아키텍처에서의 RSS (Receive Side Scaling) 확인


IBM POWER 아키텍처에서도 당연히 Redhat의 RSS (Receive Side Scaling)이 지원됩니다.  이는 다음과 같이 /proc/interrupts에서 해당 NIC을 찾아봄으로써 확인하실 수 있습니다.    아래는 POWER8 Minsky 서버에서 수행한 것인데, CPU 개수가 많아서 (2-sockets * 20-cores/socket X 4-threads/core = 160개) 보기가 힘들기 때문에 여기서는 cut 명령으로 일부 column들만 display 했습니다.  아래와 같이 실제 network cable이 연결된 NIC인 enP5p1s0f0에는 1개의 transmit queue와 4개의 receive queue가 설정되어 있는 것이 보입니다.   그리고 그 queue의 interrupt 번호는 104부터 108번까지인 것도 보실 수 있습니다.

[user612@p612-met1 ~]$ egrep 'CPU|enP' /proc/interrupts | cut -c1-40,1760-1820
           CPU0       CPU1       CPU2    CPU159
 65:          0          0          0       0  XIVE-IRQ 2088960 Edge      enP48p1s0f0
 67:          0          0          0       0  XIVE-IRQ 2088962 Edge      enP48p1s0f0-fp-0
 68:          0          0          0       0  XIVE-IRQ 2088963 Edge      enP48p1s0f0-fp-1
 69:          0          0          0       0  XIVE-IRQ 2088964 Edge      enP48p1s0f0-fp-2
 70:          0          0          0       0  XIVE-IRQ 2088965 Edge      enP48p1s0f0-fp-3
 71:          0          0          0       0  XIVE-IRQ 2088966 Edge      enP48p1s0f0-fp-4
 76:          0          0          0       0  XIVE-IRQ 2088967 Edge      enP48p1s0f0-fp-5
 77:          0          0          0       0  XIVE-IRQ 2088968 Edge      enP48p1s0f0-fp-6
 78:          0          0          0       0  XIVE-IRQ 2088969 Edge      enP48p1s0f0-fp-7
 79:          0          0          0       0  XIVE-IRQ 2088970 Edge      enP48p1s0f1
 85:          0          0          0       0  XIVE-IRQ 2088972 Edge      enP48p1s0f1-fp-0
 86:          0          0          0       0  XIVE-IRQ 2088973 Edge      enP48p1s0f1-fp-1
 87:          0          0          0       0  XIVE-IRQ 2088974 Edge      enP48p1s0f1-fp-2
 94:          0          0          0       0  XIVE-IRQ 2088975 Edge      enP48p1s0f1-fp-3
 95:          0          0          0       3  XIVE-IRQ 2088976 Edge      enP48p1s0f1-fp-4
100:          0          0          0       0  XIVE-IRQ 2088977 Edge      enP48p1s0f1-fp-5
101:          0          0          0       0  XIVE-IRQ 2088978 Edge      enP48p1s0f1-fp-6
102:          0          0          0       7  XIVE-IRQ 2088979 Edge      enP48p1s0f1-fp-7
104:          0          0          0       0  XIVE-IRQ 1028096 Edge      enP5p1s0f0-tx-0
105:          0          0          0       0  XIVE-IRQ 1028097 Edge      enP5p1s0f0-rx-1
106:          0          0          0       0  XIVE-IRQ 1028098 Edge      enP5p1s0f0-rx-2
107:          0          0          0       0  XIVE-IRQ 1028099 Edge      enP5p1s0f0-rx-3
108:      24564          0          0       0  XIVE-IRQ 1028100 Edge      enP5p1s0f0-rx-4
109:          0          0          0       0  XIVE-IRQ 1028101 Edge      enP5p1s0f1-tx-0
110:          0          0          0       0  XIVE-IRQ 1028102 Edge      enP5p1s0f1-rx-1
111:          0          0          0       0  XIVE-IRQ 1028103 Edge      enP5p1s0f1-rx-2
112:          0          0          0       0  XIVE-IRQ 1028104 Edge      enP5p1s0f1-rx-3
113:          0          0          0       0  XIVE-IRQ 1028105 Edge      enP5p1s0f1-rx-4


위 정보는 아래와 같은 방법으로도 확인하실 수 있습니다.  먼저 /sys/devices 밑에서 해당 ethernet NIC을 찾습니다.

[user612@p612-met1 ~]$ sudo find /sys/devices -name "enP5p1*"
/sys/devices/pci0005:00/0005:00:00.0/0005:01:00.0/net/enP5p1s0f0
/sys/devices/pci0005:00/0005:00:00.0/0005:01:00.1/net/enP5p1s0f1

그 다음에 msi_irqs directory 속의 interrupt 번호를 확인하면 됩니다.

[user612@p612-met1 ~]$ ls -l /sys/devices/pci0005:00/0005:00:00.0/0005:01:00.0/msi_irqs
total 0
-r--r--r-- 1 root root 65536 Oct 31 20:48 104
-r--r--r-- 1 root root 65536 Oct 31 20:48 105
-r--r--r-- 1 root root 65536 Oct 31 20:48 106
-r--r--r-- 1 root root 65536 Oct 31 20:48 107
-r--r--r-- 1 root root 65536 Oct 31 20:48 108

이렇게 찾아낸 interrupt 번호로 /proc/irq/해당번호/smp_affinity를 확인해보면 아래와 같이 무의미해보이는 숫자열이 보입니다.

[user612@p612-met1 ~]$ cat /proc/irq/104/smp_affinity
00000000,00000000,00000000,00010000,00000000

[user612@p612-met1 ~]$ cat /proc/irq/105/smp_affinity
00000000,00000000,00000000,00000000,00002000

[user612@p612-met1 ~]$ cat /proc/irq/106/smp_affinity
00000000,00000000,00000000,20000000,00000000

[user612@p612-met1 ~]$ cat /proc/irq/107/smp_affinity
00000000,00000000,00000000,00000040,00000000

[user612@p612-met1 ~]$ cat /proc/irq/108/smp_affinity
00000000,00000000,00000000,00000000,00000001


위 숫자 string은 각 숫자 하나하나가 CPU 4개를 가리키는 16진수이며, 가령 /proc/irq/107/smp_affinity의 숫자열을 2진수로 풀어놓으면 다음과 같습니다.   (16진수 4는 2^2이므로 2진수로는 0100 입니다)

(16진수) ..., 00000040, 00000000
(2진수)  ..., 0000 0000 0000 0000 0000 0000 0100 0000, 0000 0000 0000 0000 0000 0000 0000 0000

위와 같이 2진수로 풀어쓴 숫자열의 해석은, 오른쪽부터 0 또는 1 숫자 하나하나가 CPU(정확하게는 logical CPU = hyperthread = SMT)를 가리키며 1로 표시된 것이 해당 interrupt를 처리하는 CPU입니다.   즉 오른쪽부터 39번째 CPU가 해당 interrupt를 처리하는 CPU입니다. 

실제로 거기에 지정된 CPU가 해당 interrupt를 처리하는지 확인해보기 위해 iperf tool을 설치합니다.

[user612@p612-met1 ~]$ sudo yum groupinstall "Development Tools"

[user612@p612-met1 ~]$ wget https://iperf.fr/download/source/iperf-3.1.3-source.tar.gz

[user612@p612-met1 ~]$ tar -xf iperf-3.1.3-source.tar.gz

[user612@p612-met1 ~]$ cd iperf-3.1.3

[user612@p612-met1 iperf-3.1.3]$ ./configure

[user612@p612-met1 iperf-3.1.3]$ make -j8 && sudo make install

[user612@p612-met1 iperf-3.1.3]$ iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------


이 서버로 제 Windows PC에서 iperf를 client mode로 구동하겠습니다.  (Windows에서는 관리자모드로 iperf를 수행해야 합니다.)

C:\temp\iperf-3.1.3-win64>iperf3.exe -c 129.40.252.187 -P 8


이렇게 iperf client가 접속하면 서버에서는 다음과 같은 정보가 display됩니다.
...
[ 19]   0.00-10.21  sec  0.00 Bytes  0.00 bits/sec                  sender
[ 19]   0.00-10.21  sec  10.1 MBytes  8.32 Mbits/sec                  receiver
[SUM]   0.00-10.21  sec  0.00 Bytes  0.00 bits/sec                  sender
[SUM]   0.00-10.21  sec  82.6 MBytes  67.9 Mbits/sec                  receiver
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------



[user612@p612-met1 ~]$ egrep 'CPU|enP5p1s0f0' /proc/interrupts | cut -c1-40,424-450,1760-1820
           CPU0       CPU1       CPU2         CPU38      CPU39      CPU159
104:          0          0          0            0          0          0  XIVE-IRQ 1028096 Edge      enP5p1s0f0-tx-0
105:          0          0          0            0          0          0  XIVE-IRQ 1028097 Edge      enP5p1s0f0-rx-1
106:          0          0          0            0          0          0  XIVE-IRQ 1028098 Edge      enP5p1s0f0-rx-2
107:          0          0          0        44403          0          0  XIVE-IRQ 1028099 Edge      enP5p1s0f0-rx-3
108:      24714          0          0            0          0          0  XIVE-IRQ 1028100 Edge      enP5p1s0f0-rx-4


정말 107번 interrupt는 39번째 CPU core (CPU38)이 처리하는 것이 맞다는 것을 확인하실 수 있습니다.

2019년 9월 18일 수요일

IBM POWER에서 Julia를 source로부터 build 하기



Redhat 7.6 ppc64le 위에서 docker를 이용하여 Ubuntu 18.04 ppc64le 환경을 만들고 그 위에서 Julia 1.2.0을 source로부터 build하는 과정입니다.

먼저 root user로 기존에 jupyter 및 scipy-notebook이 설치된 ppc64le용 docker image를 구동합니다.

[user609@c609-kvm1 ~]$ sudo docker run -ti --rm --user root -e NB_GID=100 -e GEN_CERT=yes -e GRANT_SUDO=yes brlee/jupyter:scipy-notebook bash

먼저 julia 관련 환경 변수를 설정합니다.

root@5b95ee340ef3:~# cd /opt

root@5b95ee340ef3:/opt# export JULIA_DEPOT_PATH=/opt/julia
root@5b95ee340ef3:/opt# export JULIA_PKGDIR=/opt/julia
root@5b95ee340ef3:/opt# export JULIA_VERSION=1.2.0

root@5b95ee340ef3:/opt# mkdir /opt/julia-${JULIA_VERSION}

그리고나서 julia의 source를 github에서 download 받습니다.

root@5b95ee340ef3:/opt# cd /tmp

root@5b95ee340ef3:/tmp# git clone git://github.com/JuliaLang/julia.git

root@5b95ee340ef3:/tmp# cd julia

또한 julia build에 필요한 OS package들을 설치해야 합니다.

root@5b95ee340ef3:/tmp/julia# apt-get update

root@5b95ee340ef3:/tmp/julia# apt-get install -y gfortran fonts-dejavu gcc libreadline-dev readline-common libx11-dev libxt-dev libbz2-dev liblzma-dev libpcre2-dev libpcre3-dev  libcurl4-gnutls-dev gfortran-5-powerpc-linux-gnu texlive-latex-base texinfo texlive-fonts-extra openjdk-8-jdk openjdk-8-jdk-headless vim libmbedtls-dev libmbedcrypto1 m4 libssh2-1-dev

이렇게 설치가 되어 있더라, 현재 버전에서는 일부 파일들의 버전이 정확히 맞지가 않아서 error가 좀 있습니다.  이는 다음과 같이 그냥 다른 버전의 이름으로 soft link를 걸어서 해결할 수 있습니다.

root@5b95ee340ef3:/tmp/julia# ln -s /usr/lib/powerpc64le-linux-gnu/libmbedtls.so.10 /usr/lib/powerpc64le-linux-gnu/libmbedtls.so.12

root@5b95ee340ef3:/tmp/julia# ln -s /usr/lib/powerpc64le-linux-gnu/libmbedcrypto.so.2.8.0 /usr/lib/powerpc64le-linux-gnu/libmbedcrypto.so.3

우리가 여기서 compile할 것은 v1.2.0 입니다.

root@5b95ee340ef3:/tmp/julia# git checkout tags/v1.2.0

Build 자체는 매우 쉽습니다.  그냥 make 하시면 됩니다.   그런데 그렇게 하면 일단 error가 납니다.  다음과 같이 "ELF load command alignment not page-aligned" error 입니다.  이는 아마도 POWER architecture에서 huge page를 사용하기 때문에 발생하는 것일 수 있습니다.

root@5b95ee340ef3:/tmp/julia# nohup make -j8 &
...
Serialization  ──  1.911660 seconds
Libdl  ──────────  0.074467 seconds
Markdown  ───────  1.986755 seconds
error during bootstrap:
LoadError("sysimg.jl", 16, LoadError("/tmp/julia/usr/share/julia/stdlib/v1.2/LibGit2/src/LibGit2.jl", 21, LoadError("/tmp/julia/usr/share/julia/stdlib/v1.2/LibGit2/src/utils.jl", 44, ErrorException("error compiling version: could not load library \"libgit2\"\nlibcurl.so.4: ELF load command alignment not page-aligned"))))
rec_backtrace at /tmp/julia/src/stackwalk.c:94
record_backtrace at /tmp/julia/src/task.c:219 [inlined]
...

이 문제는 다음과 같이 몇개의 so 파일을 docker image 내의 OS file들로 교체하면 간단히 해결됩니다.

root@5b95ee340ef3:/tmp/julia# cp /usr/lib/powerpc64le-linux-gnu/libcurl.so.4.5.0 ./usr/lib/libcurl.so.4

root@5b95ee340ef3:/tmp/julia# cp /usr/lib/powerpc64le-linux-gnu/libmbedtls.so.2.8.0 ./usr/lib/libmbedtls.so.2.16.0

root@5b95ee340ef3:/tmp/julia# cp /usr/lib/powerpc64le-linux-gnu/libmbedtls.so.2.8.0 ./usr/lib/libmbedtls.so.2.6.0

root@5b95ee340ef3:/tmp/julia# cp /usr/lib/powerpc64le-linux-gnu/libmbedtls.so.2.8.0 ./deps/scratch/mbedtls-2.6.0-gpl/library/libmbedtls.so.2.6.0

root@5b95ee340ef3:/tmp/julia# cp /usr/lib/powerpc64le-linux-gnu/libssh2.so.1.0.1 ./deps/scratch/libssh2-30e9c1347e3b8baa2951db612f05e6d87fc8e2f2/src/libssh2.so.1.0.1

root@5b95ee340ef3:/tmp/julia# cp /usr/lib/powerpc64le-linux-gnu/libssh2.so.1.0.1 ./deps/scratch/libssh2-30e9c1347e3b8baa2951db612f05e6d87fc8e2f2/tests/libssh2.so.1.0.1

root@5b95ee340ef3:/tmp/julia# cp /usr/lib/powerpc64le-linux-gnu/libssh2.so.1.0.1 ./usr/lib/libssh2.so.1.0.1

그 다음에 다시 make를 수행하면 성공적으로 잘 build 됩니다.

root@5b95ee340ef3:/tmp/julia# make
...
REPL  ───────────  1.273557 seconds
Statistics  ─────  0.487972 seconds
Stdlibs total  ── 93.832328 seconds
Sysimage built. Summary:
Total ─────── 146.463495 seconds
Base: ───────  52.627857 seconds 35.9324%
Stdlibs: ────  93.832328 seconds 64.0653%
    JULIA usr/lib/julia/sys-o.a
Generating precompile statements... 898 generated in 131.715009 seconds (overhead  97.270528 seconds)
    LINK usr/lib/julia/sys.so

root@5b95ee340ef3:/tmp/julia# make install

이제 docker image size를 줄이기 위해 불필요한 file을 제거합니다.

root@5b95ee340ef3:/tmp/julia# cd ..

root@5b95ee340ef3:/tmp# rm -rf julia

그 다음에 parent OS에서 docker image를 commit하면 됩니다.

[user609@c609-kvm1 ~]$ sudo docker commit 5b95ee340ef3 brlee/jupyter:julia-1.2.0

이 image는 다음의 이름으로 public docker hub에 push해놓았습니다.

[user609@c609-kvm1 ~]$ sudo docker push brlee/jupyter:julia-1.2.0



2019년 8월 9일 금요일

REAR : Linux on POWER에서 사용가능한 OS backup 솔루션


Redhat이건 Ubuntu건 Linux on POWER의 OS backup/restore 솔루션으로 REAR(RElax-And-Recover)라는 open source tool을 이용할 수 있습니다.

REAR는 다음 URL에 사용법이나 source code 등이 자세히 나와 있습니다. 

http://relax-and-recover.org

Ubuntu 18.04 같은 경우에는 다음과 같이 정규 apt repository에 포함이 되어 있습니다.

u0017649@sys-99014:~/files$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.10
Release:        18.10
Codename:       cosmic

u0017649@sys-99014:~$ apt-cache pkgnames | grep -i rear
rear
rear-doc

REAR와 함께 install 되어야 하는 pre-requisite OS package들은 대략 다음과 같습니다.

u0017649@sys-99014:~$ sudo apt-get install -y rear rear-doc
...
The following NEW packages will be installed:
  attr isolinux keyutils libisoburn1 libnfsidmap2 libtirpc1 nfs-common rear rear-doc rpcbind syslinux-common xorriso
...

그러나 Ubuntu 16.04 같은 경우에는 다음과 같이 REAR가 apt repository에 포함되어있지 않습니다.

u0017649@sys-99404:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.2 LTS
Release:        16.04
Codename:       xenial

u0017649@sys-99404:~$ apt-cache pkgnames | grep rear

이 경우에도 당황하지 않으셔도 됩니다.  Ubuntu 18.04에 있는 최신 REAR를 download 받아서 사용할 수 있으니까요.  물론 여기서는 ppc64el용의 것을 download 받으셔야 합니다.

u0017649@sys-99014:~/REAR$ wget http://ports.ubuntu.com/ubuntu-ports/pool/universe/r/rear/rear_2.3+dfsg-1_ppc64el.deb

그리고 다음과 같이 REAR 설치에 필요한 prerequisite OS package들을 download 받습니다.

u0017649@sys-99404:~/REAR$ apt-get download attr isolinux keyutils libisoburn1 libnfsidmap2 libtirpc1 nfs-common rpcbind syslinux-common xorriso libburn4 libisoburn1 libisofs6 libevent-2.0-5
Get:1 http://ports.ubuntu.com/ubuntu-ports xenial/main ppc64el attr ppc64el 1:2.4.47-2 [24.6 kB]
Get:2 http://ports.ubuntu.com/ubuntu-ports xenial/main ppc64el isolinux all 3:6.03+dfsg-11ubuntu1 [44.6 kB]
Get:3 http://ports.ubuntu.com/ubuntu-ports xenial/main ppc64el keyutils ppc64el 1.5.9-8ubuntu1 [46.7 kB]
Get:4 http://ports.ubuntu.com/ubuntu-ports xenial/main ppc64el libnfsidmap2 ppc64el 0.25-5 [29.9 kB]
Get:5 http://ports.ubuntu.com/ubuntu-ports xenial/main ppc64el rpcbind ppc64el 0.2.3-0.2 [38.4 kB]
Get:6 http://ports.ubuntu.com/ubuntu-ports xenial/main ppc64el syslinux-common all 3:6.03+dfsg-11ubuntu1 [1,181 kB]
Get:7 http://ports.ubuntu.com/ubuntu-ports xenial/universe ppc64el libisoburn1 ppc64el 1.4.2-4ubuntu1 [335 kB]
Get:8 http://ports.ubuntu.com/ubuntu-ports xenial/universe ppc64el xorriso ppc64el 1.4.2-4ubuntu1 [263 kB]
...

Download가 다 끝난 뒤 보면 아래와 같은 file들이 보입니다.

u0017649@sys-99404:~/REAR$ ls -l
total 2948
-rw-r--r-- 1 u0017649 u0017649   24640 Sep  9  2014 attr_1%3a2.4.47-2_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649   44606 Feb 24  2016 isolinux_3%3a6.03+dfsg-11ubuntu1_all.deb
-rw-r--r-- 1 u0017649 u0017649   46694 Dec 10  2015 keyutils_1.5.9-8ubuntu1_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649  139746 Feb 17  2016 libburn4_1.4.2.pl01-1_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649  108980 Mar 13  2017 libevent-2.0-5_2.0.21-stable-2ubuntu0.16.04.1_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649  334928 Apr 18  2016 libisoburn1_1.4.2-4ubuntu1_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649  195768 Feb  5  2016 libisofs6_1.4.2-2_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649   29864 Feb 17  2014 libnfsidmap2_0.25-5_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649   70442 Sep  5  2018 libtirpc1_0.2.5-1ubuntu0.1_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649  171216 May  8 19:08 nfs-common_1%3a1.2.8-9ubuntu12.2_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649  336988 Aug  8 22:26 rear_2.3+dfsg-1_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649   38358 Nov 11  2015 rpcbind_0.2.3-0.2_ppc64el.deb
-rw-r--r-- 1 u0017649 u0017649 1181310 Feb 24  2016 syslinux-common_3%3a6.03+dfsg-11ubuntu1_all.deb
-rw-r--r-- 1 u0017649 u0017649  263420 Apr 18  2016 xorriso_1.4.2-4ubuntu1_ppc64el.deb

이를 아래와 같이 dpkg 명령으로 다 설치하면 됩니다.

u0017649@sys-99404:~/REAR$ sudo dpkg -i *
...
Setting up xorriso (1.4.2-4ubuntu1) ...
Setting up rear:ppc64el (2.3+dfsg-1) ...
Processing triggers for man-db (2.7.5-1) ...
Processing triggers for libc-bin (2.23-0ubuntu7) ...
Processing triggers for systemd (229-4ubuntu16) ...
Processing triggers for ureadahead (0.100.0-19) ...
Processing triggers for install-info (6.1.0.dfsg.1-5) ...

이제 rear 명령을 쓰실 수 있습니다.

u0017649@sys-99404:~$ which rear
/usr/sbin/rear

REAR를 통해 boot 이미지를 만들고 backup을 받으려면 USB storage(또는 USB stick)를 사용하시는 것이 일반적입니다.  USB port에 USB storage를 꽂으시고 그것이 /dev/sdc로 인식되면, 아래와 같이 일단 format을 해줍니다.  이때 당연히 USB storage 안의 기존 data는 모두 삭제되는데, label은 REAR-000으로 붙여집니다.

u0017649@sys-99404:~$ sudo rear format /dev/sdc

그리고 다음과 같이 REAR의 local config file을 업데이트합니다.

u0017649@sys-99404:~$ sudo vi /etc/rear/local.conf
OUTPUT=USB
BACKUP=NETFS
BACKUP_URL="usb:///dev/disk/by-label/REAR-000"

다음 명령으로 USB storage 안에 boot image를 만듭니다.

u0017649@sys-99404:~$ sudo rear -v mkrescue

그리고나서 아래와 같은 명령으로 OS backup을 받습니다.  이때 backup에 사용되는 format은 tar 입니다.

u0017649@sys-99404:~$ sudo rear -v mkbackup

이제 저 USB storage로부터 booting을 하여 'Recover Arch Rear'를 선택한 뒤, 'arch rear' prompt가 나오면 'rear recover' 명령을 수행하면 OS가 restore 됩니다.   저는 USB storage도 없고 물리적인 linux 서버도 없어서 restore는 테스트해보지 못했습니다만, REAR의 홈페이지에 나와 있는 유튜브 동영상 중에 캡춰한 화면의 recover 메뉴는 아래와 같습니다.




혹시 필요하신 분들을 위하여, 위에서 사용한 'REAR' directory 속의 rear 및 그 prerequisite OS package들을 download 받아둔 REAR.tgz 파일을 아래 Google drive에 올려두었습니다.

https://drive.google.com/open?id=10FjolrZSpuDl6qDKv3dKwOJyCLMxXr7l


2019년 5월 22일 수요일

ppc64le 환경에서 IBM Cloud private (ICP) 설치하기


GPU 자원에 대해 private cloud를 구축하는 고객분들이 점점 늘어나고 있습니다.  NVIDIA가 이제 virtual GPU를 CUDA에서도 지원하기는 합니다만, 주로 deep learning에 사용되는 GPU를 그렇게 virtual GPU로 나눠쓰는 것은 실질적인 이익이 별로 없습니다.  어차피 GPU 메모리가 부족한 상황이니까요.  그래서 GPU cloud를 구축할 때 사용되는 기술은 가상화보다는 docker orchestration이 대세를 이루고 있습니다.

IBM은 docker orchestration에 대해 IBM Cloud private (ICp)라는 솔루션을 제공합니다.  이는 Kubernetes 기반으로 만들어진 private cloud 솔루션이라고 할 수 있습니다.  Redhat의 OpenShift와 비슷한 솔루션이라고 보시면 됩니다.  설치도 매우 간단하며, 당연히 IBM POWER9, 즉 ppc64le 아키텍처 버전도 있습니다. 

이번 posting에서는 IBM의 POWER9 CPU와 NVIDIA V100 GPU를 장착한 AC922 서버에 ICp를 설치해보도록 하겠습니다. 
먼저 docker와 nvidia-docker를 설치해야 하는 것은 당연하고요, 그 외에 다음과 같이 사전 작업을 몇가지 해줘야 합니다.  아래 내용은 이 link에 나온 manual을 따라 한 것입니다.  참조하십시요.

https://www.ibm.com/support/knowledgecenter/en/SSBS6K_2.1.0/installing/install_containers.html

먼저 /etc/hosts에 IP를 등록하거나 DNS에 등록된 IP를 준비합니다.  원래 최소 조건이 master node, proxy node, worker node1, worker node2가 필요합니다.  Boot node는 master node와 같은 node에 있어도 괜찮습니다.  그러나 여기서는 GPU 서버인 AC922이 딱 1대 있기 때문에, 어쩔 수 없이 1대가 master node, worker node, proxy node 역할을 모두 하도록 했습니다.   그래서 /etc/hosts에 다음과 같이 IP address 하나에 4개의 이름을 주었습니다.

root@uniac922:~# cat /etc/hosts
127.0.0.1       localhost
192.168.0.20    uniac922 proxy master node1 node2

그리고 vm.max_map_count를 256K로 늘려줍니다.  이는 프로세스가 사용할 수 있는 메모리 맵 영역의 최대 수를 뜻합니다.

root@uniac922:~# sudo sysctl -w vm.max_map_count=262144
vm.max_map_count = 262144

위의 튜닝 효과가 reboot 이후에도 유효하게 하기 위해서는 아래와 같이 /etc/sysctl.conf에도 등록을 해줘야 합니다.

root@uniac922:~#  sudo vi /etc/sysctl.conf
vm.max_map_count=262144

그리고 각 node들끼리 passwd 입력 없이 ssh가 되어야 합니다.  제 경우처럼 localhost 자체로 ssh하는 경우도 마찬가지입니다.  이는 아래와 같이 해주면 됩니다.

root@uniac922:~# ssh-keygen -t rsa

root@uniac922:~# vi /etc/ssh/sshd_config
#PermitRootLogin prohibit-password
PermitRootLogin yes

root@uniac922:~# ssh-copy-id master
root@uniac922:~# ssh-copy-id proxy
root@uniac922:~# ssh-copy-id node1

미리 download 받아둔 ICp 설치 파일을 다음과 같이 docker에 load 합니다.

root@uniac922:~# ls -l *.tar.gz
-rw-rw-r-- 1 root root 6163151506 May 14 23:46 ibm-cloud-private-ppc64le-2.1.0.1.tar.gz

root@uniac922:~# tar xf ibm-cloud-private-ppc64le-2.1.0.1.tar.gz -O | docker load
...
2d67d9d7b31b: Loading layer [==================================================>]   2.56kB/2.56kB
f64ed19c4c4c: Loading layer [==================================================>]  3.072kB/3.072kB
Loaded image: ibmcom/metering-reader-ppc64le:2.1.0.1
72e8e5a1b8a4: Loading layer [==================================================>]  5.229MB/5.229MB
45f2ce399ddb: Loading layer [==================================================>]   2.56kB/2.56kB
187003a06729: Loading layer [==================================================>]  3.584kB/3.584kB
8ab0cc971235: Loading layer [==================================================>]     98MB/98MB
Loaded image: ibmcom/icp-identity-manager-ppc64le:2.1.0.1

이를 성공적으로 하고 나면 다음과 같이 수십개의 docker image들이 load된 것을 보실 수 있습니다.

root@uniac922:~# sudo docker images | grep ibmcom
ibmcom/icp-inception-ppc64le                              2.1.0.1-ee                         526770d6fda6        17 months ago       332MB
ibmcom/icp-catalog-ui-ppc64le                             2.1.0.1                            eb2a8475a640        17 months ago       725MB
ibmcom/metering-reader-ppc64le                            2.1.0.1                            f73cd423f4c6        17 months ago       177MB
ibmcom/kubernetes-ppc64le                                 v1.8.3-ee                          96d8c62383ff        17 months ago       521MB
...
ibmcom/mariadb-ppc64le                                    10.1.16                            e1d96397e3e8        2 years ago         451MB
ibmcom/pause-ppc64le                                      3.0                                0e777c06d387        3 years ago         739kB

위의 이미지들은 기본 docker image 저장 장소인 /var/lib/docker에 대략 25GB 정도의 space를 차지합니다.  혹시 / 또는 /var 파일시스템에 그런 여유 공간이 없다면 시작 전에 아래와 같이 docker의 root directory를 여유가 많은 filesystem으로 바꿔두셔야 합니다.

[root@ac922 ~]# vi /lib/systemd/system/docker.service
...
#ExecStart=/usr/bin/dockerd
ExecStart=/usr/bin/dockerd -g /data/docker

이어서 ICp configuration 파일들이 저장될 installation directory을 만듭니다.  여기서는 /opt/ibm-cloud-private-2.1.0.1 로 하겠습니다.

root@uniac922:~# mkdir /opt/ibm-cloud-private-2.1.0.1

root@uniac922:~# cd /opt/ibm-cloud-private-2.1.0.1

여기서 ibmcom/icp-inception-ppc64le:2.1.0.1-ee 이미지 속에서 cluster라는 directory 전체를 이 directory로 다음과 같이 copy합니다.

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# sudo docker run -v $(pwd):/data -e LICENSE=accept ibmcom/icp-inception-ppc64le:2.1.0.1-ee cp -r cluster /data

내용을 보면 다음과 같은 configuration file들이 보입니다.

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# ls -l ./cluster
total 20
-rw-r--r-- 1 root root 4799 May 15 14:17 config.yaml
-rw-r--r-- 1 root root   88 May 15 14:17 hosts
drwxr-xr-x 3 root root 4096 May 15 14:17 misc
-r-------- 1 root root    1 May 15 14:17 ssh_key

이 중에서 먼저 hosts에 아래와 같이 IP address를 지정해주고 설정을 해줍니다.   여기서는 모든 서버들이 다 같은 IP를 가지는 비정상적 상태라는 거 잊지 마십시요.

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# vi cluster/hosts
[master]
192.168.0.20   kubelet_extra_args='["--eviction-hard=memory.available<100Mi,nodefs.available<2Gi,nodefs.inodesFree<5%", "--image-gc-high-threshold=100%", "--image-gc-low-threshold=100%"]'

[worker]
192.168.0.20
192.168.0.20

[proxy]
192.168.0.20   kubelet_extra_args='["--eviction-hard=memory.available<100Mi,nodefs.available<2Gi,nodefs.inodesFree<5%", "--image-gc-high-threshold=100%", "--image-gc-low-threshold=100%"]'

#[management]
#4.4.4.4

그리고 다음과 같이 ssh_key를 copy 해줍니다.

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# cp ~/.ssh/id_rsa ./cluster/ssh_key

cluster/images라는 directory를 만들고, 아까 받아둔 ICp 설치 file을 거기로 copy해둡니다.

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# mkdir -p cluster/images

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# cp /home/ibm/files/ICp/ibm-cloud-private-ppc64le-2.1.0.1.tar.gz cluster/images/

그리고 cluster/config.yaml 파일을 다음과 같이 일부 수정하여 /etc/hosts를 써도 error가 나지 않도록 해줍니다.

ibm@uniac922:/opt/ibm-cloud-private-2.1.0.1$ cd cluster

ibm@uniac922:/opt/ibm-cloud-private-2.1.0.1/cluster$ sudo vi config.yaml
# loopback_dns: false
loopback_dns: true

# 위의 수정을 해주지 않고 /etc/hosts에 의존할 경우 아래와 같은 error가 납니다.
TASK [check : Validating DNS server] ************************************************************************************************************
fatal: [192.168.0.20]: FAILED! => {"changed": false, "failed": true, "msg": "A loopback IP is used in your DNS server configuration. For more details, see https://ibm.biz/dns-fails."}


그리고 ICp version 3.x 부터는 아래처럼 config.yaml에서 ansible user의 password를 32글자 이상으로 설정해야 합니다. 

[root@c633-met1 cluster]# vi config.yaml
...
## Advanced Settings
default_admin_user: admin
# default_admin_password:
default_admin_password: ibm08ibm08ibm08ibm08ibm08ibm08ibm
# ansible_user: <username>


안 그럴 경우 다음과 같은 이상한 error가 납니다.

fatal: [localhost]: FAILED! => changed=false msg: 'The password is not set. You must specify a password that meets the following criteria :  ''^([a-zA-Z0-9\-]{32,})$''


이제 다음과 같이 ibmcom/icp-inception-ppc64le:2.1.0.1-ee image를 run 시켜 install 명령을 수행합니다.

ibm@uniac922:/opt/ibm-cloud-private-2.1.0.1/cluster$ sudo docker run --net=host -t -e LICENSE=accept -v $(pwd):/installer/cluster/  ibmcom/icp-inception-ppc64le:2.1.0.1-ee install

# 혹시 이 과정 중에서 도중에 실패가 일어난다든가 할 경우, 그대로 다시 install 하지 말고 install을 uninstall로 바꿔서 깨끗히 환경을 정리한 뒤 다시 해야 합니다.  그러지 않을 경우 다음과 같은 error를 만날 수 있습니다.
fatal: [192.168.0.20]: FAILED! => {"changed": false, "failed": true, "msg": "The environment was not clean, please first uninstall the ICP and then reinstall."}


다음과 같은 메시지가 나오면 성공적으로 종료된 것입니다.  시간이 생각보다 오래 걸립니다.

...
PLAY RECAP *********************************************************************
192.168.0.20               : ok=176  changed=54   unreachable=0    failed=0
localhost                  : ok=229  changed=113  unreachable=0    failed=0
POST DEPLOY MESSAGE ************************************************************
The Dashboard URL: https://192.168.0.20:8443, default username/password is admin/admin
Playbook run took 0 days, 1 hours, 30 minutes, 3619 seconds

그리고 혹시 이렇게 설치된 ICp를 재기동하고 싶으면 docker daemon을 다음과 같이 restart 하면 됩니다.
# sudo systemctl docker restart


이후는 https://192.168.0.20:8443 로 들어가서 web browser를 접속하여 둘러보면 됩니다.   이때 default userid/passwd는 admin/admin 입니다.



처음 나오는 메뉴는 dashboard 입니다.  여기서 CPU나 메모리는 물론, deploy된 pod들과 GPU의 상태도 모니터링 가능합니다.





Namespace 관련 메뉴는 화면 왼쪽 Navigation 중 Manage 메뉴에 있습니다.   여기서 새로운 namespace를 생성할 수도 있습니다.





ICp는 local server에 자체적인 local docker image repository를 가지고 있습니다.  여기에 image를 저장하기 위해서는 먼저 다음과 같이 local repository에 login을 해야 합니다.  여기에 사용되는 userid/passwd는 물론 admin/admin 입니다.

ibm@uniac922:~$ sudo docker login mycluster.icp:8500
Username: admin
Password:
Login Succeeded

이제 현재 load된 image 중에서 하나를 다른 이름으로 tagging한 뒤 local repository에 그 새 이름으로 tagging된 image를 push 해보겠습니다.  실은 이름을 mycluster.icp:8500/"namespace"/"image이름"의 형태로 tagging해야 push가 가능합니다.  따라서 다음과 같은 이름으로 tagging하겠습니다.

ibm@uniac922:~$ sudo docker tag ibmcom/kubernetes-ppc64le:v1.8.3-ee mycluster.icp:8500/admin/kubernetes-ppc64le:v1.8.3-ee

다음과 같이 새 이름으로 tag된 image를 확인할 수 있습니다.  이어서 push 하면 됩니다.

ibm@uniac922:~$ sudo docker images | grep kubernetes-ppc64le
ibmcom/kubernetes-ppc64le                                 v1.8.3-ee                          96d8c62383ff        17 months ago       521MB
mycluster.icp:8500/kube-system/kubernetes-ppc64le         v1.8.3-ee                          96d8c62383ff        17 months ago       521MB

ibm@uniac922:~$ sudo docker push mycluster.icp:8500/kube-system/kubernetes-ppc64le:v1.8.3-ee


이렇게 push된 image는 화면 왼쪽 Navigation 중 Catalog --> Images에서 확인하실 수 있습니다.




기타 화면들의 screenshot을 올려둡니다.  보시면 job을 생성하면서 거기에 GPU를 1개 이상 할당하는 메뉴도 있습니다.
























2017년 11월 22일 수요일

ppc64le에서의 hadoop build와 구성 방법

* 아래에서 빌드한 hadoop-2.7.4.tar.gz는 아래 링크에서 download 받으실 수 있도록 google drive에 올려놓았습니다.

https://drive.google.com/open?id=1W0QYAD5DkSeY_vBHRHmu_iril4t9svJz

POWER (ppc64le) chip 위에서 hadoop을 compile하는 것은 매우 간단합니다.  그냥 https://github.com/apache/hadoop/blob/trunk/BUILDING.txt 에 나온 대로 따라 하면 됩니다.  딱 하나, protobuf 버전이 안 맞는 문제 때문에 아래와 처럼 protobuf 2.5를 별도로 설치하는 부분만 추가됩니다.

먼저 Ubuntu OS에서 기본으로 필요한 다음 package들을 설치합니다.

u0017649@sys-90043:~$ sudo apt-get install software-properties-common

u0017649@sys-90043:~$ sudo apt-get -y install maven build-essential autoconf automake libtool cmake zlib1g-dev pkg-config libssl-dev  protobuf-compiler snappy libsnappy-dev 

u0017649@sys-90043:~$ sudo apt-get install libjansson-dev bzip2 libbz2-dev fuse libfuse-dev zstd

protoc를 위해 protobuf 2.5.0의 source를 다운받아서 아래와 같이 설치합니다.  apt-get으로 설치 가능한 OS에 포함된 버전은 2.6.1인데, 묘하게도 hadoop에서는 2.5.0을 꼭 써야 한다고 고집하네요.

u0017649@sys-90043:~$ git clone --recursive https://github.com/ibmsoe/Protobuf.git
u0017649@sys-90043:~$ cd Protobuf
u0017649@sys-90043:~/Protobuf$ ./configure
u0017649@sys-90043:~/Protobuf$ make
u0017649@sys-90043:~/Protobuf$ sudo make install
u0017649@sys-90043:~/Protobuf$ which protoc
/usr/local/bin/protoc

* 참고로, 위와 같이 protobuf를 따로 해주지 않으면 아래와 같은 error 발생합니다.

[ERROR] Failed to execute goal org.apache.hadoop:hadoop-maven-plugins:3.1.0-SNAPSHOT:protoc (compile-protoc) on project hadoop-common: org.apache.maven.plugin.MojoExecutionException: protoc version is 'libprotoc 2.6.1', expected version is '2.5.0' -> [Help 1]

환경 변수도 설정합니다.

u0017649@sys-90043:~$ export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-ppc64el
u0017649@sys-90043:~$ export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
u0017649@sys-90043:~$ export MAVEN_OPTS="-Xmx2048m"

그리고나서 hadoop-2.7.4의 source를 다음과 같이 download 받습니다.   현재 최신 버전은 3.0인데, 이건 아직 안정화 버전은 아닌 것 같고, 최근 버전의 HortonWorks에 포함된 버전인 2.7.4로 하겠습니다.

u0017649@sys-90043:~$ wget http://apache.tt.co.kr/hadoop/common/hadoop-2.7.4/hadoop-2.7.4-src.tar.gz
u0017649@sys-90043:~$ tar -zxf hadoop-2.7.4-src.tar.gz
u0017649@sys-90043:~$ cd hadoop-2.7.4-src

빌드 자체는 maven으로 수행되는데, 시간은 좀 걸립니다만 상대적으로 매우 간단합니다.  아래와 같이 수행하면 빌드된 binary가 tar.gz로 묶여서 hadoop-dist/target 디렉토리에 생성됩니다.

u0017649@sys-90043:~/hadoop-2.7.4-src$ mvn package -Pdist -DskipTests -Dtar
...
main:
     [exec] $ tar cf hadoop-2.7.4.tar hadoop-2.7.4
     [exec] $ gzip -f hadoop-2.7.4.tar
     [exec]
     [exec] Hadoop dist tar available at: /home/u0017649/hadoop-2.7.4-src/hadoop-dist/target/hadoop-2.7.4.tar.gz
     [exec]
[INFO] Executed tasks
[INFO]
[INFO] --- maven-javadoc-plugin:2.8.1:jar (module-javadocs) @ hadoop-dist ---
[INFO] Building jar: /home/u0017649/hadoop-2.7.4-src/hadoop-dist/target/hadoop-dist-2.7.4-javadoc.jar
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] Apache Hadoop Main ................................. SUCCESS [  4.780 s]
[INFO] Apache Hadoop Build Tools .......................... SUCCESS [  2.711 s]
[INFO] Apache Hadoop Project POM .......................... SUCCESS [  1.633 s]
[INFO] Apache Hadoop Annotations .......................... SUCCESS [  2.645 s]
[INFO] Apache Hadoop Assemblies ........................... SUCCESS [  0.386 s]
[INFO] Apache Hadoop Project Dist POM ..................... SUCCESS [  2.546 s]
[INFO] Apache Hadoop Maven Plugins ........................ SUCCESS [  6.019 s]
[INFO] Apache Hadoop MiniKDC .............................. SUCCESS [ 11.630 s]
[INFO] Apache Hadoop Auth ................................. SUCCESS [ 12.236 s]
[INFO] Apache Hadoop Auth Examples ........................ SUCCESS [  9.364 s]
[INFO] Apache Hadoop Common ............................... SUCCESS [02:21 min]
[INFO] Apache Hadoop NFS .................................. SUCCESS [ 11.743 s]
[INFO] Apache Hadoop KMS .................................. SUCCESS [ 16.980 s]
[INFO] Apache Hadoop Common Project ....................... SUCCESS [  3.316 s]
[INFO] Apache Hadoop HDFS ................................. SUCCESS [02:42 min]
[INFO] Apache Hadoop HttpFS ............................... SUCCESS [ 34.161 s]
[INFO] Apache Hadoop HDFS BookKeeper Journal .............. SUCCESS [ 13.819 s]
[INFO] Apache Hadoop HDFS-NFS ............................. SUCCESS [  5.306 s]
[INFO] Apache Hadoop HDFS Project ......................... SUCCESS [  0.080 s]
[INFO] hadoop-yarn ........................................ SUCCESS [  0.073 s]
[INFO] hadoop-yarn-api .................................... SUCCESS [ 39.900 s]
[INFO] hadoop-yarn-common ................................. SUCCESS [ 41.698 s]
[INFO] hadoop-yarn-server ................................. SUCCESS [  0.160 s]
[INFO] hadoop-yarn-server-common .......................... SUCCESS [ 13.859 s]
[INFO] hadoop-yarn-server-nodemanager ..................... SUCCESS [ 16.781 s]
[INFO] hadoop-yarn-server-web-proxy ....................... SUCCESS [  5.143 s]
[INFO] hadoop-yarn-server-applicationhistoryservice ....... SUCCESS [ 10.619 s]
[INFO] hadoop-yarn-server-resourcemanager ................. SUCCESS [ 25.832 s]
[INFO] hadoop-yarn-server-tests ........................... SUCCESS [  6.436 s]
[INFO] hadoop-yarn-client ................................. SUCCESS [  9.209 s]
[INFO] hadoop-yarn-server-sharedcachemanager .............. SUCCESS [  4.691 s]
[INFO] hadoop-yarn-applications ........................... SUCCESS [  0.052 s]
[INFO] hadoop-yarn-applications-distributedshell .......... SUCCESS [  4.187 s]
[INFO] hadoop-yarn-applications-unmanaged-am-launcher ..... SUCCESS [  2.589 s]
[INFO] hadoop-yarn-site ................................... SUCCESS [  0.052 s]
[INFO] hadoop-yarn-registry ............................... SUCCESS [  8.977 s]
[INFO] hadoop-yarn-project ................................ SUCCESS [  4.737 s]
[INFO] hadoop-mapreduce-client ............................ SUCCESS [  0.271 s]
[INFO] hadoop-mapreduce-client-core ....................... SUCCESS [ 28.766 s]
[INFO] hadoop-mapreduce-client-common ..................... SUCCESS [ 18.916 s]
[INFO] hadoop-mapreduce-client-shuffle .................... SUCCESS [  6.326 s]
[INFO] hadoop-mapreduce-client-app ........................ SUCCESS [ 12.547 s]
[INFO] hadoop-mapreduce-client-hs ......................... SUCCESS [  8.090 s]
[INFO] hadoop-mapreduce-client-jobclient .................. SUCCESS [ 10.544 s]
[INFO] hadoop-mapreduce-client-hs-plugins ................. SUCCESS [  2.727 s]
[INFO] Apache Hadoop MapReduce Examples ................... SUCCESS [  7.638 s]
[INFO] hadoop-mapreduce ................................... SUCCESS [  3.216 s]
[INFO] Apache Hadoop MapReduce Streaming .................. SUCCESS [  6.935 s]
[INFO] Apache Hadoop Distributed Copy ..................... SUCCESS [ 15.235 s]
[INFO] Apache Hadoop Archives ............................. SUCCESS [  4.425 s]
[INFO] Apache Hadoop Rumen ................................ SUCCESS [  7.658 s]
[INFO] Apache Hadoop Gridmix .............................. SUCCESS [  5.281 s]
[INFO] Apache Hadoop Data Join ............................ SUCCESS [  3.525 s]
[INFO] Apache Hadoop Ant Tasks ............................ SUCCESS [  2.382 s]
[INFO] Apache Hadoop Extras ............................... SUCCESS [  4.387 s]
[INFO] Apache Hadoop Pipes ................................ SUCCESS [  0.031 s]
[INFO] Apache Hadoop OpenStack support .................... SUCCESS [  6.296 s]
[INFO] Apache Hadoop Amazon Web Services support .......... SUCCESS [ 14.099 s]
[INFO] Apache Hadoop Azure support ........................ SUCCESS [  6.764 s]
[INFO] Apache Hadoop Client ............................... SUCCESS [  8.594 s]
[INFO] Apache Hadoop Mini-Cluster ......................... SUCCESS [  1.873 s]
[INFO] Apache Hadoop Scheduler Load Simulator ............. SUCCESS [  8.096 s]
[INFO] Apache Hadoop Tools Dist ........................... SUCCESS [  8.972 s]
[INFO] Apache Hadoop Tools ................................ SUCCESS [  0.039 s]
[INFO] Apache Hadoop Distribution ......................... SUCCESS [01:00 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 15:09 min
[INFO] Finished at: 2017-11-21T22:31:05-05:00
[INFO] Final Memory: 205M/808M
[INFO] ------------------------------------------------------------------------


이제 이렇게 빌드된 tar.gz을 가지고 hadoop을 (비록 1대이지만) 기본 구성하는 것을 해보겠습니다.

가령 Minsky 서버로 docker 기반의 cloud 서비스를 해주는 Nimbix cloud의 가상 머신을 사용하고 계시다면, 유일한 persistent storage인 /data에 hadoop을 설치하셔야 합니다.  그 외의 directory들에 설치하면 이 Nimbix instance를 reboot 하면 다 초기화 되어 없어져 버립니다.  이는 Nimbix가 진짜 가상 머신이 아니라 docker instance이기 때문입니다.

아래와 같이 /data 밑에 그냥 hadoop tar.gz 파일을 풀어놓으면 설치는 끝납니다.

u0017649@sys-90043:~$ cd /data
u0017649@sys-90043:/data$ tar -zxf /home/u0017649/hadoop-2.7.4-src/hadoop-dist/target/hadoop-2.7.4.tar.gz
u0017649@sys-90043:/data$ cd hadoop-2.7.4

이제 기본 환경 변수를 설정합니다.  JAVA_HOME도 위에서처럼 제대로 설정해주셔야 합니다.

u0017649@sys-90043:/data/hadoop-2.7.4$ export HADOOP_INSTALL=/data/hadoop-2.7.4
u0017649@sys-90043:/data/hadoop-2.7.4$ export PATH=$PATH:$HADOOP_INSTALL/bin:$HADOOP_INSTALL/sbin

일단 hadoop binary가 제대로 작동하는지 확인합니다.

u0017649@sys-90043:/data/hadoop-2.7.4$ hadoop version
Hadoop 2.7.4
Subversion Unknown -r Unknown
Compiled by u0017649 on 2017-11-22T03:17Z
Compiled with protoc 2.5.0
From source with checksum 50b0468318b4ce9bd24dc467b7ce1148
This command was run using /data/hadoop-2.7.4/share/hadoop/common/hadoop-common-2.7.4.jar

그리고나서 configuration directory에 들어가 기본 설정을 다음과 같이 해줍니다.

u0017649@sys-90043:/data/hadoop-2.7.4$ cd etc/hadoop

u0017649@sys-90043:/data/hadoop-2.7.4/etc/hadoop$ vi hadoop-env.sh
...
#export JAVA_HOME=${JAVA_HOME}
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-ppc64el
...

u0017649@sys-90043:/data/hadoop-2.7.4/etc/hadoop$ vi core-site.xml
<configuration>
 <property>
  <name>fs.default.name</name>
  <value>hdfs://localhost:9000</value>
 </property>

 <property>
  <name>hadoop.tmp.dir</name>
  <value>/data/hadoop-2.7.4/hadoop-${user.name}</value>
 </property>
</configuration>

u0017649@sys-90043:/data/hadoop-2.7.4/etc/hadoop$ vi mapred-site.xml
<configuration>
 <property>
  <name>mapred.job.tracker</name>
  <value>localhost:9001</value>
 </property>

 <property>
  <name>mapred.local.dir</name>
  <value>${hadoop.tmp.dir}/mapred/local</value>
 </property>

 <property>
  <name>mapred.system.dir</name>
  <value>${hadoop.tmp.dir}/mapred/system</value>
 </property>
</configuration>

slaves 파일에는 자기 자신인 localhost를 적어 줍니다.  그러면 자기 자신이 namenode도 되고 datanode도 되는 것입니다.

u0017649@sys-90043:/data/hadoop-2.7.4/etc/hadoop$ cat slaves
localhost

이제 hadoop을 기동시켜 볼텐데, 그러자면 먼저 localhost 자신에 대해서도 passwd 없이 "ssh localhost" 와 "ssh 0.0.0.0"이 가능하도록 ssh-keygen 및 ssh-copy-id가 수행되어야 합니다.

이제 namenode 포맷을 합니다.

u0017649@sys-90043:~$ hadoop namenode -format
...
17/11/21 23:53:38 INFO namenode.FSImageFormatProtobuf: Image file /data/hadoop-2.7.4/hadoop-u0017649/dfs/name/current/fsimage.ckpt_0000000000000000000 of size 325 bytes saved in 0 seconds.
17/11/21 23:53:38 INFO namenode.NNStorageRetentionManager: Going to retain 1 images with txid >= 0
17/11/21 23:53:38 INFO util.ExitUtil: Exiting with status 0
17/11/21 23:53:38 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at sys-90043/172.29.160.241
************************************************************/

그리고나서 hadoop과 yarn을 start 합니다.

u0017649@sys-90043:~$ start-all.sh
...
node-sys-90043.out
starting yarn daemons
starting resourcemanager, logging to /data/hadoop-2.7.4/logs/yarn-u0017649-resourcemanager-sys-90043.out
localhost: starting nodemanager, logging to /data/hadoop-2.7.4/logs/yarn-u0017649-nodemanager-sys-90043.out

다음과 같이 기초적인 hdfs 명령을 수행해 봅니다.  잘 되는 것을 보실 수 있습니다.

u0017649@sys-90043:~$ hadoop fs -df
Filesystem                    Size   Used   Available  Use%
hdfs://localhost:9000  36849713152  24576  5312647168    0%

u0017649@sys-90043:~$ hadoop fs -mkdir -p /user/u0017649
u0017649@sys-90043:~$ hadoop fs -mkdir input

u0017649@sys-90043:~$ hadoop fs -ls -R
drwxr-xr-x   - u0017649 supergroup          0 2017-11-21 23:58 input
-rw-r--r--   3 u0017649 supergroup        258 2017-11-21 23:58 input/hosts

u0017649@sys-90043:~$ hadoop fs -text input/hosts
127.0.0.1       localhost
127.0.1.1       ubuntu1604-dr-01.dal-ebis.ihost.com     ubuntu1604-dr-01
# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.29.160.241  sys-90043