1. K8SM (Kubernetes Mesos)?


K8SM는 Apache Mesos에서 Google의 Kubernetes를 사용 할 수 있도록 개발 된 Mesos Framework 입니다.
초기 K8SM은 Mesosphere 팀에서 Kubernetes v0.14를 기준으로 개발 되었다가, Kubernetes v1.0 버전이 릴리즈 되면서, Kubernetes로 통합이 된 것으로 알고 있습니다.

K8SM을 구성하려면 Apache Mesos와 Google Kubernetes에 대한 이해가 있어야 합니다.
– Apache Mesos
https://www.yongbok.net/blog/apache-mesos-cluster-resource-management/

– Google Kubernetes
https://www.yongbok.net/blog/google-kubernetes-container-cluster-manager/

 

 

2. K8SM – Architecture


K8SM에 대해 제 나름 대로 그려 봤습니다.
(원본은 https://github.com/GoogleCloudPlatform/kubernetes/blob/master/contrib/mesos/docs/architecture.md 에서 확인 가능 합니다.)

원리는 아래와 같습니다.

1. 사용자가 Dockerfile 또는 YAML 파일을 작성하여 적절한 곳에 저장 및 업로드 합니다.
2. 사용자가 kubectl 명령어를 통해 Pods를 구성 하도록 요청 합니다.
3. API Server가 이 정보를 ETCD에 저장 합니다.
4. Scheduler가 ETCD에 저장 된 정보를 가지고, ZooKeeper에 Mesos Master의 리더를 물어 봅니다.
5. 리더 Mesos Master는 Mesos Slave 중 Workload가 낮은 서버를 선택 하여 작업을 지시 합니다.
6. Mesos Slave는 kubelet(executor)를 실행하여, 작업을 수행하고 proxy를 실행 합니다.
7. Mesos Slave가 Container 또는 Pods에 문제가 생겼을 때 Mesos Master로 보고 합니다.
8. API Server가 이를 감지하여, Controller Manager에 요청을 하여 문제를 해결 합니다.

kubernetes_mesos_architecture_v1.x
Fig 1. The architecture diagram of Kubernetes Framework for Apache Mesos
3. K8SM – 구성


본 구성은 Ubuntu 14.04 LTS 64bit에서 테스트 되었으며, 위의 아키텍처와 같게 구성 될 것이고, Hostname과 IP 정보는 다음과 같습니다.

HostName                     IP
etcd-0                   172.17.1.1
etcd-1                   172.17.1.2
etcd-2                   172.17.1.3
mesos-master-0           172.17.1.4
mesos-master-1           172.17.1.5
mesos-master-2           172.17.1.6
mesos-master-3           172.17.1.7
kubernetes-mesos         172.17.1.8
kubernetes-minion-0      172.17.1.9
kubernetes-minion-1      172.17.1.10
kubernetes-minion-2      172.17.1.11
kubernetes-minion-3      172.17.1.12

만일, 물리 서버 1대 또는 개인 PC로 가상화를 통해 구성 할 생각이면, 아래 Docker를 활용 하는 방법도 있습니다.
https://github.com/ruo91/docker-kubernetes-mesos
4. K8SM – ETCD Cluster


ETCD를 빌드하기 위해서는 Go Language가 필요 합니다.
따라서, Go Language를 설치 후 ETCD를 빌드 합니다.

– Go Language 설치

root@ruo91:~# curl -o /opt/golang.sh -L "https://raw.githubusercontent.com/ruo91/golang-scripts/master/golang-auto.sh"
root@ruo91:~# chmod a+x /opt/golang.sh
root@ruo91:~# /opt/golang.sh
root@ruo91:~# source /etc/profile

 

– ETCD 설치
최신 버전도 좋지만, release 버전을 통해 설치 하겠습니다.

root@ruo91:~# git clone https://github.com/coreos/etcd /opt/etcd-source \
root@ruo91:~# cd /opt/etcd-source
root@ruo91:~# git checkout -b release-2.1 origin/release-2.1
root@ruo91:~# ./build && mv bin /opt/etcd
root@ruo91:~# cd .. && rm -rf etcd-source
root@ruo91:~# echo '# etcd' >> /etc/profile
root@ruo91:~# echo 'export ETCD=/opt/etcd' >> /etc/profile
root@ruo91:~# echo 'export PATH=$PATH:$ETCD' >> /etc/profile
root@ruo91:~# echo '' >> /etc/profile
root@ruo91:~# source /etc/profile

 

– ETCD Clustering

각각의 서버마다 실행 하시면 됩니다.
* etcd-0

root@ruo91:~# etcd \
--name "cluster-0" \
--data-dir "/tmp/etcd" \
--initial-cluster-state "new" \
--initial-cluster-token "etcd-cluster" \
--listen-peer-urls "http://0.0.0.0:2380" \
--listen-client-urls "http://0.0.0.0:4001" \
--advertise-client-urls "http://0.0.0.0:4001" \
--initial-advertise-peer-urls "http://172.17.1.1:2380" \
--initial-cluster "cluster-0=http://172.17.1.1:2380,cluster-1=http://172.17.1.2:2380,cluster-2=http://172.17.1.3:2380" \
> /tmp/etcd-cluster.log 2>&1 &

 

* etcd-1

root@ruo91:~# etcd \
--name "cluster-1" \
--data-dir "/tmp/etcd" \
--initial-cluster-state "new" \
--initial-cluster-token "etcd-cluster" \
--listen-peer-urls "http://0.0.0.0:2380" \
--listen-client-urls "http://0.0.0.0:4001" \
--advertise-client-urls "http://0.0.0.0:4001" \
--initial-advertise-peer-urls "http://172.17.1.2:2380" \
--initial-cluster "cluster-0=http://172.17.1.1:2380,cluster-1=http://172.17.1.2:2380,cluster-2=http://172.17.1.3:2380" \
> /tmp/etcd-cluster.log 2>&1 &

 

* etcd-2

root@ruo91:~# etcd \
--name "cluster-2" \
--data-dir "/tmp/etcd" \
--initial-cluster-state "new" \
--initial-cluster-token "etcd-cluster" \
--listen-peer-urls "http://0.0.0.0:2380" \
--listen-client-urls "http://0.0.0.0:4001" \
--advertise-client-urls "http://0.0.0.0:4001" \
--initial-advertise-peer-urls "http://172.17.1.3:2380" \
--initial-cluster "cluster-0=http://172.17.1.1:2380,cluster-1=http://172.17.1.2:2380,cluster-2=http://172.17.1.3:2380" \
> /tmp/etcd-cluster.log 2>&1 &

5. K8SM – Mesos Master


Mesos를 패키지로 설치 할 경우 ZooKeeper도 함께 설치 되므로, ZooKeeper 서버를 따로 구성 하지 않아도 됩니다.
만일, ZooKeeper 서버를 따로 구성 하려는 경우 본문의 ZooKeeper 관련 설정은 무시 하면 됩니다.

– Mesos 설치

root@ruo91:~# apt-get update && apt-get install -y add-apt-key
root@ruo91:~# apt-key adv --keyserver keyserver.ubuntu.com --recv E56151BF
root@ruo91:~# echo "deb http://repos.mesosphere.io/ubuntu trusty main" > /etc/apt/sources.list.d/mesosphere.list
root@ruo91:~# apt-get update && apt-get install -y mesos

 

– ZooKeeper 설정

root@ruo91:~# echo '# ZooKeeper Quorum' >> /etc/zookeeper/conf/zoo.cfg
root@ruo91:~# echo 'server.1=172.17.1.4:2888:3888' >> /etc/zookeeper/conf/zoo.cfg
root@ruo91:~# echo 'server.2=172.17.1.5:2888:3888' >> /etc/zookeeper/conf/zoo.cfg
root@ruo91:~# echo 'server.3=172.17.1.6:2888:3888' >> /etc/zookeeper/conf/zoo.cfg
root@ruo91:~# echo 'server.4=172.17.1.7:2888:3888' >> /etc/zookeeper/conf/zoo.cfg

 

– ZooKeeper MyID 설정

* mesos-master-0

root@ruo91:~# echo '1' >> /etc/zookeeper/myid

 

* mesos-master-1

root@ruo91:~# echo '2' >> /etc/zookeeper/myid

 

* mesos-master-2

root@ruo91:~# echo '3' >> /etc/zookeeper/myid

 

* mesos-master-3

root@ruo91:~# echo '4' >> /etc/zookeeper/myid

 

– ZooKeeper 시작
각각의 서버마다 실행 하시면 됩니다.

root@ruo91:~# service zookeeper start

 

– Mesos Master 시작
각각의 서버마다 실행 하시면 됩니다.
실행 할때 주의 할 점이 있는데, mesos 0.2x 버전대에서 quorum 옵션 값이 2이 상이 되면 리더 Master 서버가 죽는 문제가 있습니다.

이 문제는 값을 1로 하면 해결이 되며, 해당 링크는 https://gist.github.com/jaytaylor/3fced64bcf1fecc61d18 에서 확인 하실 수 있습니다.

root@ruo91:~# mesos-master \
--quorum=1 \
--cluster=mesos-cluster \
--work_dir=/var/lib/mesos \
--zk=zk://172.17.1.4:2181,172.17.1.5:2181,172.17.1.6:2181,172.17.1.7:2181/mesos \
> /tmp/mesos-master.log 2>&1 &

6. K8SM – Minion & Mesos Slave


Minion에 Container가 실행 되므로, Docker가 설치 되어 있어야 합니다.
또한, Mesos Slave가 kubelet(executor), proxy를 실행 하기 위해서는 Kubernetes Server가 설치 되어 있어야 합니다.
– Docker 설치

root@ruo91:~# apt-get install -y docker.io

 

– Docker 설정 (AUFS 사용자만 설정 하시면 됩니다.)
Docker 데몬 옵션 설정 파일에 스토리지 드라이버를 OverlayFS로 변경 후 재시작 합니다.
OverlayFS로 설정하는 이유는 Docker 1.x 버전대 중에 AUFS를 기본으로 사용하는데, 이 AUFS가 리눅스 커널과 충돌이 잦습니다.

Container 실행 중에 HostOS가 멈춤 현상이 발생 할 수 있기 때문에,
Docker 공식 문서에서도 AUFS 대신에, Devicemapper, Btrfs, OverlayFS를 사용 하도록 권장 하고 있습니다.
(참고로, OverlayFS는 Linux Kernel 3.10+ 이상에서 사용 가능 합니다.)

root@ruo91:~# nano /etc/default/docker.io
DOCKER_OPTIONS="-s overlay --dns-server 8.8.8.8 --dns-server 8.8.4.4 --dns-search google-public-dns-a.google.com"

 

기존의 Docker 이미지 저장소를 삭제하고 재시작 합니다.

root@ruo91:~# service docker.io stop
root@ruo91:~# rm -rf /var/lib/docker
root@ruo91:~# service docker.io start

 

– Mesos 설치

root@ruo91:~# apt-get update && apt-get install -y add-apt-key
root@ruo91:~# apt-key adv --keyserver keyserver.ubuntu.com --recv E56151BF
root@ruo91:~# echo "deb http://repos.mesosphere.io/ubuntu trusty main" > /etc/apt/sources.list.d/mesosphere.list
root@ruo91:~# apt-get update && apt-get install -y mesos

 

– Mesos Slave 시작
각각의 서버마다 실행 하시면 됩니다.

root@ruo91:~# mesos-slave \
--master=zk://172.17.1.4:2181,172.17.1.5:2181,172.17.1.6:2181,172.17.1.7:2181/mesos \
> /tmp/mesos-slave.log 2>&1 &

 

– Kubernetes 빌드
kubernetes는 Docker를 활용하여 빌드가 됩니다. 따라서, Docker가 미리 설치 되어 있어야 합니다.
또한, 빌드시 주의 할 점이 있는데, KUBERNETES_CONTRIB 변수를 설정 하지 않으면, 빌드 완료시에 K8SM 관련 바이너리를 얻을 수 없습니다.

root@ruo91:~# git clone https://github.com/GoogleCloudPlatform/kubernetes /opt/k8s
root@ruo91:~# cd k8s
root@ruo91:~# export KUBERNETES_CONTRIB=mesos
root@ruo91:~# make release

 

– Kubernetes Server 설정
빌드가 완료 되면 _output 디렉토리에 파일이 생성 됩니다.
여기서 필요한 파일은 server만 필요 하므로 client 파일은 SCP나 FTP로 파일을 따로 보관 바랍니다.

_output/release-tars/kubernetes-client-linux-amd64.tar.gz
_output/release-tars/kubernetes-server-linux-amd64.tar.gz
root@ruo91:~# tar -C /opt -xzvf _output/release-tars/kubernetes-server-linux-amd64.tar.gz
root@ruo91:~# echo '# Kubernetes Server' >> /etc/profile
root@ruo91:~# echo 'export K8S_HOME=/opt/kubernetes' >> /etc/profile
root@ruo91:~# echo 'export PATH=$PATH:$K8S_HOME/server/bin' >> /etc/profile
root@ruo91:~# source /etc/profile

7. K8SM – Kubernetes Mesos Framework


K8SM도 기존 Kubernetes의 API Server, Scheduler, Controller Manager 서버를 km 바이너리로 실행 합니다.
따라서, 위 “K8SM – Minion & Mesos Slave”에서 언급한 “kubernetes-server-linux-amd64.tar.gz” 파일이 필요로 합니다.
(해당 server 파일을 /opt 디렉토리에 업로드 하였다는 가정하에 진행 하겠습니다.)
– Kubernetes Server 설정

root@ruo91:~# tar -C /opt -xzvf /opt/kubernetes-server-linux-amd64.tar.gz
root@ruo91:~# echo '# Kubernetes Server' >> /etc/profile
root@ruo91:~# echo 'export K8S_HOME=/opt/kubernetes' >> /etc/profile
root@ruo91:~# echo 'export PATH=$PATH:$K8S_HOME/server/bin' >> /etc/profile
root@ruo91:~# source /etc/profile

 

– Mesos Cloud 설정 파일 생성

Mesos의 Master에 대한 설정을 해줘야 합니다. ZooKeeper를 사용하여 Mesos Master의 리더를 선별을 하도록 사용중이면,
아래와 같이 ZooKeeper 서버를 추가 해주면 됩니다.

root@ruo91:~# cat > /opt/mesos-cloud.conf << EOF
[mesos-cloud]
mesos-master = zk://172.17.1.4:2181,172.17.1.5:2181,172.17.1.6:2181/mesos
EOF

 

만일, Mesos Master를 단일로 운용 중이라면 아래와 같이 Mesos Master만 추가 해주면 됩니다.

root@ruo91:~# cat > /opt/mesos-cloud.conf << EOF
[mesos-cloud]
mesos-master = 172.17.1.4:5050
EOF

 

– K8SM 실행
K8SM의 실행 순서는 API Server -> Controller Manager -> Scheduler 로 합니다.

* API Server

root@ruo91:~# km apiserver \
--port=8080 \
--address=0.0.0.0 \
--cloud-provider=mesos \
--cloud-config=/opt/mesos-cloud.conf \
--service-cluster-ip-range=10.0.42.1/16 \
--etcd-servers=http://172.17.1.1:4001,http://172.17.1.2:4001,http://172.17.1.3:4001 \
--v=1 > /tmp/apiserver.log 2>&1 &

 

* Controller Manager

root@ruo91:~# km controller-manager \
--master=172.17.1.8:8080 \
--cloud-provider=mesos\
--cloud-config=/opt/mesos-cloud.conf \
--v=1 > /tmp/controller-manager.log 2>&1 &

 

* Scheduler

root@ruo91:~# km scheduler \
--address=0.0.0.0 \
--mesos-user=root \
--api-servers=172.17.1.8:8080 \
--etcd-servers=http://172.17.1.1:4001,http://172.17.1.2:4001,http://172.17.1.3:4001 \
--mesos-master=zk://172.17.1.4:2181,172.17.1.5:2181,172.17.1.6:2181,172.17.1.7:2181/mesos \
--v=2 > /tmp/scheduler.log 2>&1 &

8. K8SM – Web Server


K8SM은 Mesos와 Kubernetes 조합이므로 Mesos Master의 UI, Kubernetes의 API Server UI 두 개를 통해 웹으로 확인이 가능합니다.
이 부분을 특정 도메인을 통해 접속이 이뤄지도록 Nginx에 리버스 프록시 설정을 하겠습니다.

– Nginx 설치

root@ruo91:~# apt-get install -y nginx

 

– Nginx Reverse Proxy 설정

root@ruo91:~# nano /etc/nginx/conf.d/k8sm.conf
# Mesos master web ui
server {
    listen  80;
    server_name mesos.yongbok.net;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://172.17.1.4:5050;
        client_max_body_size 10M;
    }
}
# Kubernetes apiserver web ui
server {
    listen  80;
    server_name kubernetes.yongbok.net;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://172.17.1.8:8080;
        client_max_body_size 10M;
    }
}
root@ruo91:~# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@ruo91:~# nginx -s reload

9. K8SM – Client & Test


Pods를 생성하기 위해서는 kubectl 바이너리가 필요합니다.
따라서, 위 “K8SM – Minion & Mesos Slave”에서 언급한 “kubernetes-client-linux-amd64.tar.gz” 파일이 필요로 합니다.
(해당 client 파일을 /opt 디렉토리에 업로드 하였다는 가정하에 진행 하겠습니다.)

– Kubernetes Client 설정

root@ruo91:~# tar -C /opt -xzvf /opt/kubernetes-client-linux-amd64.tar.gz
root@ruo91:~# echo '# Kubernetes Client' >> /etc/profile
root@ruo91:~# echo 'export K8S_HOME=/opt/kubernetes' >> /etc/profile
root@ruo91:~# echo 'export PATH=$PATH:$K8S_HOME/client/bin' >> /etc/profile
root@ruo91:~# source /etc/profile

 

Mesos Master에 K8SM이 정상적으로 등록이 되었는지 확인 해보겠습니다.
(-s 옵션은 API Server를 뜻하며, 실행시 k8sm-scheduler이 나오지 않는다면 구성에 문제가 있는 것입니다.)

root@ruo91:~# docker exec kubernetes-mesos kubectl get services
NAME             LABELS                                    SELECTOR   IP(S)         PORT(S)     AGE
k8sm-scheduler   component=scheduler,provider=k8sm         <none>     10.0.18.129   10251/TCP   33s
kubernetes       component=apiserver,provider=kubernetes   <none>     10.0.0.1      443/TCP     1m

 

예제 Nginx YAML 파일을 통해 Pods를 구성 해봅니다.

root@ruo91:~# docker exec kubernetes-mesos kubectl create -f /opt/nginx.yaml -s 172.17.1.8:8080
pods/nginx

 

Pods를 확인 해봤을때, STATUS 부분에 Pending 상태로 되어있는 경우, Docker Images를 받아오는 중이라고 생각 하시면 됩니다.
또한, Running의 경우 Container가 실행 중이라는 뜻입니다.

root@ruo91:~# docker exec kubernetes-mesos kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
nginx     1/1       Running   0          14s

 

Web Server 부분에서 설정한 도메인으로 접속 하면 웹에서 해당 UI를 확인 해볼 수 있습니다.

– Mesos Master WEB UI
k8sm_mesos_web_ui

– Mesos Master WEB UI – Framework
k8sm_mesos_web_ui_framework

– Mesos Master WEB UI – Framework ID
k8sm_mesos_web_ui_framework_id

– Kubernetes Web UI
k8sm_apiserver

– Kubernetes Web UI – Pods
k8sm_apiserver_pods
Reference


– Google Kubernetes
https://github.com/googlecloudplatform/kubernetes

– Mesosphere Kubernetes Mesos
https://github.com/mesosphere/kubernetes-mesos

– ruo91/docker-kubernetes-mesos
https://github.com/ruo91/docker-kubernetes-mesos

– Yongbok Blog: Apache Mesos Cluster Resource Management
https://www.yongbok.net/blog/apache-mesos-cluster-resource-management/

– Yongbok Blog: Google Kubernetes- Container Cluster Manager
https://www.yongbok.net/blog/google-kubernetes-container-cluster-manager/

Thanks 🙂