2018년 1월 11일 목요일

ppc64le에서의 flannel 구성 : host 서버 외부로의 docker container network 구성


서로 다른 두대의 물리적 서버에 각각 위치한 docker container들끼리 network 통신을 할 수 있도록 설정하는 방법입니다.  한줄 요약하자면 여기에는 flanneld를 구성해야 하며, 이를 위해서는 먼저 etcd를 구성해야 합니다.

이 테스트에는 아래 site들을 참조했습니다.

http://docker-k8s-lab.readthedocs.io/en/latest/docker/docker-etcd.html
http://docker-k8s-lab.readthedocs.io/en/latest/docker/docker-flannel.html
http://cloudgeekz.com/1016/configure-flannel-docker-power.html
https://www.ibm.com/developerworks/community/blogs/mhhaque/entry/Docker_And_Kubernetes_Cluster_on_Power_with_RHEL7_Part_2_etcd_flanneld_daemons_on_master_node?lang=en
https://www.ibm.com/developerworks/community/blogs/mhhaque/entry/Docker_And_Kubernetes_Cluster_on_Power_with_RHEL7_Part_3_flanneld_docker_daemons_on_Docker_Container_node?lang=en

서버 환경은 IBM POWER8 Ubuntu 16.04 ppc64le이며, 두 대 서버의 hostname과 IP는 다음과 같습니다.

물리적서버 #1    sys-90725    172.29.160.221
물리적서버 #2    sys-90754    172.29.160.207


먼저 etcd를 설치합니다.  이건 flanneld 구성을 위해 필요한 일종의 key-value store입니다.  Ubuntu OS에 포함된 것을 그대로 이용하시면 됩니다.

u0017649@sys-90725:~$ sudo apt-get install etcd

설정값은 아래와 같이 /etc/default/etcd에 정리합니다.

u0017649@sys-90725:~$ sudo vi /etc/default/etcd
ETCD_NAME=sys-90725
ETCD_DATA_DIR="/var/lib/etcd/default"
ETCD_LISTEN_CLIENT_URLS="http://172.29.160.221:2379,http://127.0.0.1:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://172.29.160.221:2379"

물론 서버#2에는 거기에 맞는 hostname과 IP를 입력해야 합니다.

u0017649@sys-90754:~$ sudo vi /etc/default/etcd
ETCD_NAME=sys-90754
ETCD_DATA_DIR="/var/lib/etcd/default"
ETCD_LISTEN_CLIENT_URLS="http://172.29.160.270:2379,http://127.0.0.1:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://172.29.160.207:2379"

etcd를 start하고, 제대로 작동 중인지 확인합니다.

u0017649@sys-90725:~$ sudo systemctl enable etcd
u0017649@sys-90725:~$ sudo systemctl start etcd
u0017649@sys-90725:~$ sudo systemctl status etcd
● etcd.service - etcd - highly-available key value store
   Loaded: loaded (/lib/systemd/system/etcd.service; enabled; vendor preset: enabl
   Active: active (running) since Mon 2018-01-08 03:11:40 EST; 6min ago
     Docs: https://github.com/coreos/etcd
           man:etcd
 Main PID: 6100 (etcd)
   CGroup: /system.slice/etcd.service
           └─6100 /usr/bin/etcd

이어서, flanneld 구성 정보를 다음과 같이 json 파일로 작성합니다.  두 대의 서버에 동일한 내용으로 작성합니다.

u0017649@sys-90725:~$ vi flannel-config-vxlan.json
{
   "Network": "10.172.29.0/16",
    "SubnetLen": 24,
    "Backend": {
       "Type": "vxlan",
       "VNI": 1
    }
}

이제 이 file을 아래와 같이 etcd에 집어넣습니다.   /atomic.io/network/config은 물리적 file name도 아니고 internet 주소도 아님에 유의하세요.

u0017649@sys-90725:~$ sudo etcdctl set /atomic.io/network/config < flannel-config-vxlan.json

제대로 들어갔는지 확인은 아래와 같이 합니다.

u0017649@sys-90725:~$ sudo etcdctl get /atomic.io/network/config
{
   "Network": "10.172.29.0/16",
    "SubnetLen": 24,
    "Backend": {
       "Type": "vxlan",
       "VNI": 1
    }
}

etcd가 정상 작동 중인지는 아래와 같은 방법으로 하실 수 있습니다.

u0017649@sys-90725:~$ curl -L http://sys-90725:2379/v2/keys/atomic.io/network/config
{"action":"get","node":{"key":"/atomic.io/network/config","value":"{\n   \"Network\": \"10.172.29.0/16\",\n    \"SubnetLen\": 24,\n    \"Backend\": {\n       \"Type\": \"vxlan\",\n       \"VNI\": 1\n    }\n}\n","modifiedIndex":4,"createdIndex":4}}

u0017649@sys-90725:~$ etcdctl cluster-health
member ce2a822cea30bfca is healthy: got healthy result from http://0.0.0.0:2379
cluster is healthy


이제 flannel를 설치해야 하는데, 이건 아직 Ubuntu OS에 들어있지 않습니다.  별 수 없이 build를 해야 하는데, 여기에 버전 1.7 이상의 golang을 쓰셔야 합니다.  Default로 있는 golang 1.6을 쓰시면 error가 나니 유의하십시요.

u0017649@sys-90725:~$ sudo apt-get install linux-libc-dev golang-1.9 golang-1.9-go

u0017649@sys-90754:~$ sudo rm /usr/bin/go
u0017649@sys-90754:~$ sudo ln -s /usr/lib/go-1.9/bin/go /usr/bin/go

그냥 github의 flannel을 그대로 복제하여 build하면 역시 또 error가 납니다.  해서 다음과 같이 약간의 꼼수가 필요합니다.  즉, src/github.com/coreos라는 directory를 먼저 만들고, 그 속에 들어가서 github을 복제하십시요.

u0017649@sys-90725:~$ export GOPATH=$(pwd)
u0017649@sys-90725:~$ mkdir -p src/github.com/coreos
u0017649@sys-90725:~$ cd src/github.com/coreos
u0017649@sys-90725:~/src/github.com/coreos$ git clone https://github.com/coreos/flannel.git

이제 build 시작하기 전에, Makefile에 손을 좀 대야 합니다.  이유는 Makefile에 ppc64le도 있긴 한데 amd64를 default로 채택하게 되어 있기 때문에, 그를 ppc64le로 바꾸는 작업입니다.  우리는 여기서 make targ.gz을 할 것이니, 많은 entry 중에서 그 부분만 놔두고 #으로 막으면 됩니다.
(또는 그냥 ~/src/github.com/coreos/flannel 에 들어가서 "make dist/flanneld"만 수행해도 됩니다.  필요한 건 flanneld 뿐이거든요.)

u0017649@sys-90725:~/src/github.com/coreos$ cd flannel
u0017649@sys-90725:~/src/github.com/coreos/flannel$ export CGO_ENABLED=1

u0017649@sys-90725:~/src/github.com/coreos/flannel$ vi Makefile
# Default tag and architecture. Can be overridden
#TAG?=$(shell git describe --tags --dirty)
TAG?=v0.9.0-34-gab368026-ppc64le   # from https://quay.io/repository/coreos/flannel-git?tab=tags
#ARCH?=amd64
ARCH?=ppc64le
#GO_VERSION=1.8.3
GO_VERSION=1.9.2
...
tar.gz:
#       ARCH=ppc64le make dist/flanneld-ppc64le
#       tar --transform='flags=r;s|-ppc64le||' -zcvf dist/flannel-$(TAG)-linux-ppc64le.tar.gz -C dist flanneld-ppc64le mk-docker-opts.sh ../README.md
#       tar -tvf dist/flannel-$(TAG)-linux-ppc64le.tar.gz
#       ARCH=ppc64le make dist/flanneld.exe
#       tar --transform='flags=r;s|-ppc64le||' -zcvf dist/flannel-$(TAG)-windows-ppc64le.tar.gz -C dist flanneld.exe mk-docker-opts.sh ../README.md
#       tar -tvf dist/flannel-$(TAG)-windows-ppc64le.tar.gz
        ARCH=ppc64le make dist/flanneld-ppc64le
        tar --transform='flags=r;s|-ppc64le||' -zcvf dist/flannel-$(TAG)-linux-ppc64le.tar.gz -C dist flanneld-ppc64le mk-docker-opts.sh ../README.md
        tar -tvf dist/flannel-$(TAG)-linux-ppc64le.tar.gz
#       ARCH=arm make dist/flanneld-arm
#       tar --transform='flags=r;s|-arm||' -zcvf dist/flannel-$(TAG)-linux-arm.tar.gz -C dist flanneld-arm mk-docker-opts.sh ../README.md
#       tar -tvf dist/flannel-$(TAG)-linux-arm.tar.gz
#       ARCH=arm64 make dist/flanneld-arm64
#       tar --transform='flags=r;s|-arm64||' -zcvf dist/flannel-$(TAG)-linux-arm64.tar.gz -C dist flanneld-arm64 mk-docker-opts.sh ../README.md
#       tar -tvf dist/flannel-$(TAG)-linux-arm64.tar.gz
#       ARCH=s390x make dist/flanneld-s390x
#       tar --transform='flags=r;s|-s390x||' -zcvf dist/flannel-$(TAG)-linux-s390x.tar.gz -C dist flanneld-s390x mk-docker-opts.sh ../README.md
#       tar -tvf dist/flannel-$(TAG)-linux-s390x.tar.gz

그 다음에 make tar.gz을 합니다.

u0017649@sys-90725:~/src/github.com/coreos/flannel$ make tar.gz

오래 걸리지 않아 아래와 같이 tar.gz이 만들어집니다.

u0017649@sys-90725:~/src/github.com/coreos/flannel$ ls -l dist/*.tar.gz
-rw-rw-r-- 1 u0017649 u0017649 8179227 Jan  8 23:26 dist/flannel-v0.9.0-34-gab368026-ppc64le-linux-ppc64le.tar.gz

이걸 적절한 위치(여기서는 /usr/local/bin)에 풀어놓습니다.

u0017649@sys-90725:~/src/github.com/coreos/flannel$ cd /usr/local/bin
u0017649@sys-90725:/usr/local/bin$ sudo tar -xvf ~/src/github.com/coreos/flannel/dist/flannel-v0.9.0-34-gab368026-ppc64le-linux-ppc64le.tar.gz
flanneld
mk-docker-opts.sh
README.md

flanneld 구성에 들어가기 전에 먼저 docker daemon을 stop 시키고 docker0도 삭제합니다.

u0017649@sys-90725:~$ sudo systemctl stop docker.service
u0017649@sys-90725:~$ sudo ip link delete docker0

이제 다음과 같이 /lib/systemd/system/flanneld.service 와 /etc/default/flanneld 파일을 만들어 systemctl에 flanneld 서비스를 등록합니다.

u0017649@sys-90725:~$ sudo vi  /lib/systemd/system/flanneld.service
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service

[Service]
Type=notify
EnvironmentFile=-/etc/default/flanneld
ExecStart=/usr/local/bin/flanneld -etcd-endpoints=${FLANNEL_ETCD} -etcd-prefix=${FLANNEL_ETCD_KEY} $FLANNEL_OPTIONS
Restart=on-failure

[Install]
WantedBy=multi-user.target
RequiredBy=docker.service


u0017649@sys-90725:~$ sudo vi /etc/default/flanneld
# Flanneld configuration options
# etcd url location.  Point this to the server where etcd runs
FLANNEL_ETCD="http://172.29.160.221:2379"
# etcd config key.  This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_KEY="/atomic.io/network"
# Any additional options that you want to pass
FLANNEL_OPTIONS="-ip-masq=true"

이제 flanneld를 start 하고, 정상 작동하는지 확인합니다.

u0017649@sys-90725:~$ sudo systemctl start flanneld

u0017649@sys-90725:~$ sudo systemctl status flanneld
● flanneld.service - Flanneld overlay address etcd agent
   Loaded: loaded (/lib/systemd/system/flanneld.service; disabled; vendor preset: enabled)
   Active: active (running) since Wed 2018-01-10 20:21:19 EST; 28s ago
 Main PID: 10666 (flanneld)
    Tasks: 10
   Memory: 8.8M
      CPU: 266ms
   CGroup: /system.slice/flanneld.service
           └─10666 /usr/local/bin/flanneld -etcd-endpoints=http://172.29.160.221:2379 -etcd-prefix=/atomic.io

Jan 10 20:21:19 sys-90725 flanneld[10666]: I0110 20:21:19.761758   10666 main.go:238] Installing signal handl
Jan 10 20:21:19 sys-90725 flanneld[10666]: I0110 20:21:19.764142   10666 main.go:353] Found network config -
Jan 10 20:21:19 sys-90725 flanneld[10666]: I0110 20:21:19.764234   10666 vxlan.go:120] VXLAN config: VNI=1 Po
Jan 10 20:21:19 sys-90725 flanneld[10666]: I0110 20:21:19.830878   10666 local_manager.go:201] Found previous
Jan 10 20:21:19 sys-90725 flanneld[10666]: I0110 20:21:19.859766   10666 local_manager.go:220] Allocated leas
Jan 10 20:21:19 sys-90725 flanneld[10666]: I0110 20:21:19.860247   10666 main.go:300] Wrote subnet file to /r
Jan 10 20:21:19 sys-90725 flanneld[10666]: I0110 20:21:19.860273   10666 main.go:304] Running backend.
Jan 10 20:21:19 sys-90725 systemd[1]: Started Flanneld overlay address etcd agent.
Jan 10 20:21:19 sys-90725 flanneld[10666]: I0110 20:21:19.862149   10666 vxlan_network.go:60] watching for ne
Jan 10 20:21:19 sys-90725 flanneld[10666]: I0110 20:21:19.889547   10666 main.go:396] Waiting for 22h59m59.94

이제 보면 /run/flannel/subnet.env 이라는 파일이 생성되고 그 속에 관련 환경변수 정보가 기록된 것을 보실 수 있습니다.

u0017649@sys-90725:~$ cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.172.0.0/16
FLANNEL_SUBNET=10.172.61.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

flannel.1이라는 interface도 새로 생성되는데, 다음과 같습니다.

u0017649@sys-90725:~$ ifconfig flannel.1
flannel.1 Link encap:Ethernet  HWaddr 66:bc:02:fe:88:b3
          inet addr:10.172.61.0  Bcast:0.0.0.0  Mask:255.255.255.255
          inet6 addr: fe80::64bc:2ff:fefe:88b3/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:846 errors:0 dropped:0 overruns:0 frame:0
          TX packets:679 errors:0 dropped:8 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:77685 (77.6 KB)  TX bytes:77345 (77.3 KB)

이제 이 정보를 이용해 docker daemon의 설정값을 바꾸어 줍니다.

u0017649@sys-90725:~$ sudo vi /etc/systemd/system/multi-user.target.wants/docker.service
...
#ExecStart=/usr/bin/dockerd -H fd://
EnvironmentFile=-/run/flannel/subnet.env
ExecStart=/usr/bin/dockerd -H fd:// --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU} --iptables=false --ip-masq=false

그 다음에 docker를 살립니다.

u0017649@sys-90725:~$ sudo systemctl daemon-reload
u0017649@sys-90725:~$ sudo systemctl start docker.service

이제 netstat -rn을 해보면 다음과 같이 flannel.1이라는 interface가 gateway로 뜬 것을 보실 수 있습니다.

u0017649@sys-90725:~$ netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         172.29.128.13   0.0.0.0         UG        0 0          0 ibmveth0
10.172.23.0     10.172.23.0     255.255.255.0   UG        0 0          0 flannel.1
10.172.61.0     0.0.0.0         255.255.255.0   U         0 0          0 docker0
172.29.128.0    0.0.0.0         255.255.192.0   U         0 0          0 ibmveth0


u0017649@sys-90725:~$ ip -4 a|grep inet
    inet 127.0.0.1/8 scope host lo
    inet 172.29.160.221/18 brd 172.29.191.255 scope global ibmveth0
    inet 10.172.61.0/32 scope global flannel.1
    inet 10.172.61.1/24 scope global docker0

이제 두 서버#1,#2에서 각각 docker container를 띄우고, ip address를 확인합니다.


서버 #1

u0017649@sys-90725:~$ docker run -ti --rm bsyu/caffe-ibm:v0.2 bash

root@73b40d9d2a5b:/# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 02:42:0a:ac:3d:02
          inet addr:10.172.61.2  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:950 errors:0 dropped:0 overruns:0 frame:0
          TX packets:851 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3402207 (3.4 MB)  TX bytes:84232 (84.2 KB)


root@73b40d9d2a5b:~# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 02:42:0a:ac:3d:02
          inet addr:10.172.61.2  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:931 errors:0 dropped:0 overruns:0 frame:0
          TX packets:838 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0


서버 #2

u0017649@sys-90754:~$ docker run -ti --rm bsyu/caffe-ibm:v0.2 bash

root@bfb4da5e6b06:/# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 02:42:0a:ac:05:02
          inet addr:10.172.5.2  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:86 errors:0 dropped:0 overruns:0 frame:0
          TX packets:106 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:12926 (12.9 KB)  TX bytes:11738 (11.7 KB)


서버 #2의 container에서 서버 #1의 container로 ping을 해보고 이어서 ssh를 해보겠습니다.  (물론 서버 #1의 container에는 openssh-server 및 root login 허용 작업을 미리 해놓아야 합니다.)

root@bfb4da5e6b06:/# ping 10.172.61.2
PING 10.172.61.2 (10.172.61.2) 56(84) bytes of data.
64 bytes from 10.172.61.2: icmp_seq=1 ttl=62 time=1.01 ms
64 bytes from 10.172.61.2: icmp_seq=2 ttl=62 time=0.739 ms
^C
--- 10.172.61.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.739/0.877/1.016/0.141 ms

root@bfb4da5e6b06:/# ssh 10.172.61.2
root@10.172.61.2's password:
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-104-generic ppc64le)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Thu Jan 11 01:44:26 2018 from 10.172.5.2
root@73b40d9d2a5b:~# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 02:42:0a:ac:3d:02
          inet addr:10.172.61.2  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:1030 errors:0 dropped:0 overruns:0 frame:0
          TX packets:904 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3410576 (3.4 MB)  TX bytes:91883 (91.8 KB)

root@73b40d9d2a5b:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
none             35G   27G  6.6G  80% /
tmpfs           2.0G     0  2.0G   0% /dev
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/sda2        35G   27G  6.6G  80% /etc/hosts
shm              64M     0   64M   0% /dev/shm
tmpfs           2.0G     0  2.0G   0% /sys/firmware


다 잘 되는 것을 확인하실 수 있습니다.  다음과 같이 scp에 의한 파일 전송도 잘 됩니다.

root@73b40d9d2a5b:~# echo "I love donut" > /tmp/docker1

root@73b40d9d2a5b:~# logout
Connection to 10.172.61.2 closed.

root@bfb4da5e6b06:/# scp 10.172.61.2:/tmp/docker1 /tmp
root@10.172.61.2's password:
docker1                                                                    100%   13     0.0KB/s   00:00

root@bfb4da5e6b06:/# cat /tmp/docker1
I love donut

2번 container에 traceroute를 설치한 뒤 1번 container로의 route 경로를 살펴보면 다음과 같습니다.

root@bfb4da5e6b06:/# apt-get install traceroute

root@bfb4da5e6b06:/# traceroute 10.172.61.2
traceroute to 10.172.61.2 (10.172.61.2), 30 hops max, 60 byte packets
 1  10.172.5.1 (10.172.5.1)  0.215 ms  0.030 ms  0.026 ms
 2  10.172.61.0 (10.172.61.0)  3.198 ms  3.390 ms  3.353 ms
 3  10.172.61.2 (10.172.61.2)  3.654 ms  3.926 ms  3.890 ms


즉, 먼저 서버 #2의 docker0를 통해 flannel.1으로 나가 서버 #1의 flannel.1을 거쳐 docker0로 들어가는 것입니다.

u0017649@sys-90754:~$ ip -4 a|grep inet
    inet 127.0.0.1/8 scope host lo
    inet 172.29.160.207/18 brd 172.29.191.255 scope global ibmveth0
    inet 10.172.5.0/32 scope global flannel.1
    inet 10.172.5.1/24 scope global docker0

u0017649@sys-90725:~$ ip -4 a|grep inet
    inet 127.0.0.1/8 scope host lo
    inet 172.29.160.221/18 brd 172.29.191.255 scope global ibmveth0
    inet 10.172.61.0/32 scope global flannel.1
    inet 10.172.61.1/24 scope global docker0

----------------------------------------

참고로 docker container 안에서 sshd를 살리고 root login을 허용하는 방법은 다음과 같습니다.

root@73b40d9d2a5b:/# apt-get install openssh-server

root@73b40d9d2a5b:/# vi /etc/ssh/sshd_config
#PermitRootLogin prohibit-password
PermitRootLogin yes

root@73b40d9d2a5b:/# /etc/init.d/ssh start



댓글 없음:

댓글 쓰기