Update: 2015-12-06

Kubernetes Logo

Kubernetes?


결론부터 말하자면, Kubernetes는 구글이 자사의 Backend 부분의 Container들을 쉽게 관리하기 위해 고안 된 프로젝트라고 보시면 됩니다.

사실, 구글은 Borg라는 프로젝트를 만들어 Container를 다년간 관리 해왔는데, 이것(Borg)의 경험을 녹여 Kubernetes라는 오픈소스를 2013년에 오픈하게 된 것입니다. 관련 논문은 여기를 참고 하시면 됩니다.

오픈소스로 발표하고 나서, 마이크로소프트(MS), 레드햇, IBM, Docker, CoreOS, Meso Sphere, Salt Stack등등의 회사들이 개발에 참여하여 급속도로 빠르게 성장 하는중 입니다.

Kubernetes의 주요 기능은 여러 호스트에서 Container의 응용프로그램 배포와 유지 보수, 확장을 지원 해줍니다.
또한, 현재 포스팅 내용은 Kubernetes v1.1 버전에서 테스트 및 작성 되었습니다.

Architecture


Kubernetes는 크게 Master 서버와 Minion 서버로 이루어져 있습니다.

1. Master
– etcd
CoreOS에서 만든 Key/Value 저장소이며, 여기에 kubernetes에 관련 된 정보를 담아 두는 곳으로 쓰입니다.
– API Server
Master의 중심이 되는 것이 API 서버 입니다.
– Scheduler
client로 부터 kubectl 명령어를 통해 지시받은 작업을 스케줄러가 이를 가지고 있다가 API 서버로 보내주는 역할을 합니다.
– Controller Manager (Replication Controller)
Controller Manager는 Pods의 Replication 부분을 모니터링하고, 여기에 변경 사항이 있으면 API Server를 통해 Pods의 증감/감소 설정을 하는 역할을 담당 합니다.
예를 들어 Pods의 replicas 수가 지정된 개수보다 낮거나 높으면 자동으로 지정 된 수를 지키도록 합니다.


2. Minion

Minion은 Container가 실행 될 수 있는 서버를 말하며, minion = docker server 라고 이해 하시면 됩니다.

– Docker
dotCloud Inc에서 개발하여 Docker라는 이름으로 오픈소스로 발표 되었고,
사용하기 불편했던, LXC(LinuX Containers)를 쉽게 사용할 수 있게 되었습니다.
이 Docker는 HostOS의 커널을 그대로 사용하되, HostOS와 Container OS의 다른 부분만을 패키징하여 독립 된 환경을 제공 해주는 도구 입니다.
– Kubelet
Minion을 제어하는 agent이며, 단일 Container 또는 Pod를 생성 해주는 역할을 담당 합니다.
– Kube Proxy
간단한 L3 프록시이며, kubelet에서 생성한 Pods의 RR(Round Robin)을 담당하는 역할을 합니다.
– Pod
여러 Container들의 묶음이 Pod 입니다.
ex)
redis-group-1(redis-1, redis-2, redis-3, redis-4. … redis-N)
nginx-group-1(nginx-1, nginx-2, nginx-3, nginx-4. … nginx-N)
– cAdvisor
Container의 자원을 모니터링 하는 소프트웨어입니다.
단일 Container 또는 Pods에 대해 모니터링하고, 이를 Kubelet에 전달 합니다.
– Label
Pods에 이름을 붙이는 것으로, 하나의 Pod에 여러가지의 Label을 붙일 수가 있습니다.
예를 들면 환경을 나타내는 ‘Production’, ‘Development’, ‘Staging’ 또는 역할을 나타내는 ‘Frontend’, ‘Backend’, ‘Worker’, ‘Logger’를 붙일 수가 있습니다.

Kubernetes Architecture

Figure 1. Kubernetes Architecture
(https://github.com/GoogleCloudPlatform/kubernetes/blob/master/DESIGN.md)

 

좀 더  이해가 쉽게 GIF로 만들어 봤습니다.

k8s_architecture

 

구성


위의 아키텍처대로 리눅스에서 구성할 것이며, 공통 부분에는 ‘root@ruo91:~#’로 표시 될 것이고, 개별 설정은 다르게 표시 될 것입니다.

* 실제 물리 서버가 1대 밖에 없는 분들은 Docker를 가지고 응용하여 구축 해볼 수 있습니다.
Github: https://github.com/ruo91/docker-kubernetes

구성할 서버는 총 7대, etcd-cluster-0, 1, 2, kubernetes-master, kubernetes-minion-0, 1, kubernetes-client 입니다.

    Hostname			    IP 
etcd-cluster-0			172.17.1.1
etcd-cluster-1			172.17.1.2
etcd-cluster-2			172.17.1.3
kubernetes-master		172.17.1.4
kubernetes-minion-0		172.17.1.5
kubernetes-minion-1		172.17.1.6
kubernetes-client		172.17.1.7


– Overlay network

Kubernetes를 사용하면 몇가지 네트워크 문제에 봉착하게 됩니다.
1. Container <-> Container
2. Pod <-> Pod
3. Pod <-> Service
4. External <-> Internal
여러가지 방법이 있겠지만, 간단한 해결 방법으로는 CoreOS의 Flannel을 사용하여 해결 하는 것입니다.
이 Flannel을 Master, Minion 서버에 실행해야 합니다.

공통설정


Hostname 별칭을 설정 합니다.

root@ruo91:~# echo "# Kubernetes" >> /etc/hosts
root@ruo91:~# echo "172.17.1.4 kubernetes-master" >> /etc/hosts
root@ruo91:~# echo "172.17.1.5 kubernetes-minion-0" >> /etc/hosts
root@ruo91:~# echo "172.17.1.6 kubernetes-minion-1" >> /etc/hosts
root@ruo91:~# echo "172.17.1.7 kubernetes-client" >> /etc/hosts

SSH 연결시 비밀번호를 묻지 않도록 설정합니다.

root@ruo91:~# sed -i 's/\#AuthorizedKeysFile/AuthorizedKeysFile/g' /etc/ssh/sshd_config
root@ruo91:~# service ssh restart
root@ruo91:~# ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
root@ruo91:~# cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys

kubernetes-client 서버에서 master, minion 0, 1 서버들의 authorized_keys 파일의 내용을 추가 합니다.

root@ruo91:~# ssh root@kubernetes-master "cat ~/.ssh/authorized_keys" >> ~/.ssh/authorized_keys
root@ruo91:~# ssh root@kubernetes-minion-0 "cat ~/.ssh/authorized_keys" >> ~/.ssh/authorized_keys
root@ruo91:~# ssh root@kubernetes-minion-1 "cat ~/.ssh/authorized_keys" >> ~/.ssh/authorized_keys

이후 kubernetes-client 서버의 authorized_keys 파일을 master, minion 0, 1 서버에 배포 합니다.

root@ruo91:~# scp ~/.ssh/authorized_keys root@kubernetes-master:~/.ssh/authorized_keys
root@ruo91:~# scp ~/.ssh/authorized_keys root@kubernetes-minion-0:~/.ssh/authorized_keys
root@ruo91:~# scp ~/.ssh/authorized_keys root@kubernetes-minion-1:~/.ssh/authorized_keys

 

ETCD 구성


– ETCD 설치

etcd-cluster-0, 1, 2 서버에서 아래와 같이 설치와 설정을 합니다.

root@etcd-cluster:~# cd /opt
root@etcd-cluster:~# wget \
https://github.com/coreos/etcd/releases/download/v2.2.0/etcd-v2.2.0-linux-amd64.tar.gz
root@etcd-cluster:~# tar xzvf etcd-v2.2.0-linux-amd64.tar.gz
root@etcd-cluster:~# mv etcd-v2.2.0-linux-amd64 etcd
root@etcd-cluster:~# rm -rf etcd*.tar.gz

 

– ETCD Profile 설정

root@etcd-cluster:~# echo '# etcd' >> /etc/profile
root@etcd-cluster:~# echo 'export ETCD=/opt/etcd' >> /etc/profile
root@etcd-cluster:~# echo 'export PATH=$PATH:$ETCD' >> /etc/profile
root@etcd-cluster:~# echo '' >> /etc/profile
root@etcd-cluster:~# source /etc/profile

 

– 클러스터 설정

etcd-cluster-0

root@etcd-cluster-0:~# etcd \
--name "cluster-0" \
--data-dir "/tmp/etcd" \
--listen-peer-urls "http://0.0.0.0:2380" \
--initial-advertise-peer-urls "http://$(ip a s | grep 'eth0' | grep 'inet' | cut -d '/' -f 1 | awk '{ print $2 }'):2380" \
--listen-client-urls "http://0.0.0.0:4001" \
--advertise-client-urls "http://0.0.0.0:4001" \
--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" \
--initial-cluster-state "new" \
--initial-cluster-token "etcd-cluster" \
> /tmp/etcd-cluster.log 2>&1 &

etcd-cluster-1

root@etcd-cluster-1:~# etcd \
--name "cluster-1" \
--data-dir "/tmp/etcd" \
--listen-peer-urls "http://0.0.0.0:2380" \
--initial-advertise-peer-urls "http://$(ip a s | grep 'eth0' | grep 'inet' | cut -d '/' -f 1 | awk '{ print $2 }'):2380" \
--listen-client-urls "http://0.0.0.0:4001" \
--advertise-client-urls "http://0.0.0.0:4001" \
--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" \
--initial-cluster-state "new" \
--initial-cluster-token "etcd-cluster" \
> /tmp/etcd-cluster.log 2>&1 &

etcd-cluster-2

root@etcd-cluster-2:~# etcd \
--name "cluster-2" \
--data-dir "/tmp/etcd" \
--listen-peer-urls "http://0.0.0.0:2380" \
--initial-advertise-peer-urls "http://$(ip a s | grep 'eth0' | grep 'inet' | cut -d '/' -f 1 | awk '{ print $2 }'):2380" \
--listen-client-urls "http://0.0.0.0:4001" \
--advertise-client-urls "http://0.0.0.0:4001" \
--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" \
--initial-cluster-state "new" \
--initial-cluster-token "etcd-cluster" \
> /tmp/etcd-cluster.log 2>&1 &

 

 

Kubernetes 빌드


Kubernetes를 구축하기 위해서는 HostOS에 Docker가 설치 되어 있어야 합니다.
설치 방법은 생략하며 링크를 통해 설치 하시기 바랍니다.

https://docs.docker.com/


– kubernetes 빌드

Kubernetes 설치는 kubernetes-master에서 진행하겠으며, Google의 Github 저장소에서 받아 빌드를 진행 하겠습니다.
(최신 개발 버전으로 사용하고 싶다면 checkout 과정은 무시 하고 바로 make 과정으로 넘어 가시면 됩니다.)

root@kubernetes-master:~# git clone https://github.com/kubernetes/kubernetes /opt/kubernetes-source
root@kubernetes-master:~# cd /opt/kubernetes-source
root@kubernetes-master:~# git checkout -b release-1.1 origin/release-1.1
root@kubernetes-master:~# make quick-release

빌드가 완료 되면 _output 디렉토리에서 client, server의 tar 파일을 가져 옵니다.

root@kubernetes-master:~# mv _output/release-tars/kubernetes-client-linux-amd64.tar.gz /opt
root@kubernetes-master:~# mv _output/release-tars/kubernetes-server-linux-amd64.tar.gz /opt
root@kubernetes-master:~# cd .. && rm -rf /opt/kubernetes-source

Master 서버에서는 바로 압축을 풀어 줍니다.

root@kubernetes-master:~# tar xzvf kubernetes-server*.tar.gz

kubernetes client, kubernetes minion 0, 1 서버들에게 scp를 통해 해당 파일을 배포를 합니다.

root@kubernetes-master:~# scp kubernetes-client*.tar.gz root@kubernetes-client:/opt
root@kubernetes-master:~# scp kubernetes-server*.tar.gz root@kubernetes-minion-0:/opt
root@kubernetes-master:~# scp kubernetes-server*.tar.gz root@kubernetes-minion-1:/opt


– Kubernetes Profile 설정

kubernetes client, master, minion 0, 1에 아래와 같이 환경 설정을 해줍니다.

root@kubernetes:~# echo '' >> /etc/profile
root@kubernetes:~# echo '# Kubernetes' >> /etc/profile
root@kubernetes:~# echo 'export KUBERNETES_HOME=/opt/kubernetes' >> /etc/profile
root@kubernetes:~# echo 'export PATH=$PATH:$KUBERNETES_HOME/server/bin:$KUBERNETES_HOME/client/bin' >> /etc/profile

 

 

Kubernetes – Master


Master 서버에 관련 된 데몬을 실행 하기전 Flannel를 실행하여 Overlay network를 사용하도록 해야 합니다.

– Flannel

Flannel에서 지정한 네트워크 범위를 사용하기 위해서는 ETCD에 최조 등록을 해야 Flanneld가 실행 되었을때,
해당 범위를 할당 받을 수 있게 됩니다. 따라서, Flannel 네트워크 범위를 적절하게 설정하여 한번만 실행 해주면 됩니다.

root@kubernetes-master:~# cat > /opt/flannel.json << EOF
{
    "Network": "10.0.0.0/16",
    "Backend": {
        "Type": "vxlan"
    }
}
EOF
root@kubernetes-master:~# curl -L http://172.17.1.1:4001/v2/keys/overlay/network/config \
-XPUT --data-urlencode value/opt/flannel.json

그외 추가 옵션은 여기를 통해 살펴 보시기 바랍니다.

– Flannel 빌드
GitHub에서 Flannel을 다운받아 설치 후 실행 합니다.

root@kubernetes-master:~# git clone https://github.com/coreos/flannel.git /opt/flannel
root@kubernetes-master:~# cd /opt/flannel
root@kubernetes-master:~# ./build \
root@kubernetes-master:~# echo '# flannel'>>/etc/profile
root@kubernetes-master:~# echo "export FLANNEL_HOME=/opt/flannel">>/etc/profile
root@kubernetes-master:~# echo 'export PATH=$PATH:$FLANNEL_HOME/bin'>>/etc/profile
root@kubernetes-master:~# echo ''>>/etc/profile
root@kubernetes-master:~# source /etc/profile


– Flannel 실행

root@kubernetes-master:~# flanneld \
-iface=eth0 \
-log_dir="/tmp/flannel.log" \
-etcd-prefix="/overlay/network" \
-etcd-endpoints="http://172.17.1.1:4001,http://172.17.1.2:4001,http://172.17.1.3:4001" \
--v=0 > /tmp/flanneld.log 2>&1 &


– Bridge Interface 생성

Flannel의 네트워크를 사용하려면 전용 브릿지를 생성 후에 사용하도록 해야 합니다.
(Flannel의 CIDR을 사용 하도록 설정 합니다.)

root@kubernetes-master:~# export FLANNEL_CIDR="$(ip a s flannel.1 | grep -v 'inet6' | grep 'inet' | cut -d ':' -f 2 | awk '{ print $2}' | sed 's/0\/16/1\/24/g')"
root@kubernetes-master:~# brctl addbr br0
root@kubernetes-master:~# ip addr add $FLANNEL_CIDR dev br0
root@kubernetes-master:~# ip link set dev br0 up


– API Server

API 서버는 public(0.0.0.0)으로 binding 해주는 것이 일반적입니다. 경우에 따라서 내부에서만 사용 할 경우 내부 IP로 설정 하시면 됩니다. 또한, –service-cluster-ip-range 옵션을 필수로 지정 해줘야 하는데, 이 옵션은 Pod에서 실행 될 Container들의 IP를 할당 해주도록 하는 옵션입니다. 이 옵션의 경우 Flannel의 CIDR 범위 보다 한단계 아래로 지정 해주시면 됩니다.

Flannel 브릿지의 CIDR을 확인 하고,

root@kubernetes-master:~# ip a s | grep flannel.1 | grep inet
    inet 10.0.42.0/16 scope global flannel.1

기본 API 포트와 etcd cluster 서버 정보를 적절하게 지정하여 실행 하면 됩니다.

root@kubernetes-master:~# kube-apiserver \
--port=8080 \
--address=0.0.0.0 \
--kubelet-port=10250 \
--service-cluster-ip-range=10.0.42.0/24
--etcd_servers=http://172.17.1.1:4001,http://172.17.1.2:4001,http://172.17.1.3:4001
--v=0 > /var/log/k8s-apiserver.log 2>&1 &


– Scheduler

Scheduler도 마찬가지로 외부에서 접근이 가능하도록 public(0.0.0.0)으로 binding 해줘야 합니다.
(이것 역시 내부로 사용할 경우 내부 IP로 지정 해주시면 됩니다.)

스케줄러의 기본 포트는 10251이고, Master(api server)의 IP와 포트를 적절하게 입력 하면 됩니다.

root@kubernetes-master:~# kube-scheduler \
--address=0.0.0.0 \
--master=172.17.1.4:8080 \
--v=0 > /var/log/k8s-scheduler.log 2>&1 &


– Controller Manager (Replication Controller)

외부에서 연결이 가능하도록 public(0.0.0.0)으로 설정하고, Master(api server)의 IP와 포트를 입력 하면 됩니다.
(이것 역시 내부로 사용할 경우 내부 IP로 지정 해주시면 됩니다.)

root@kubernetes-master:~# kube-controller-manager \
--address=0.0.0.0 \
--master=172.17.1.4:8080 \
--v=0 > /var/log/k8s-controller-manager.log 2>&1 &

 

 

Kubernetes – Minion


Minion은 0, 1 서버 모두 같은 방식으로 데몬을 실행 하기전 Flannel를 실행하여 Overlay network를 사용하도록 해야 합니다.

– Flannel

GitHub에서 Flannel을 다운받아 설치 후 실행 합니다.

root@kubernetes-master:~# git clone https://github.com/coreos/flannel.git /opt/flannel
root@kubernetes-master:~# cd /opt/flannel
root@kubernetes-master:~# ./build \
root@kubernetes-master:~# echo '# flannel'>>/etc/profile
root@kubernetes-master:~# echo "export FLANNEL_HOME=/opt/flannel">>/etc/profile
root@kubernetes-master:~# echo 'export PATH=$PATH:$FLANNEL_HOME/bin'>>/etc/profile
root@kubernetes-master:~# echo ''>>/etc/profile
root@kubernetes-master:~# source /etc/profile


– Flannel 실행

root@kubernetes-master:~# flanneld \
-iface=eth0 \
-log_dir="/tmp/flannel.log" \
-etcd-prefix="/overlay/network" \
-etcd-endpoints="http://172.17.1.1:4001,http://172.17.1.2:4001,http://172.17.1.3:4001" \
--v=0 > /tmp/flanneld.log 2>&1 &

– Docker Interface 재설정
Docker 데몬이 실행 될 때 자동으로 docker0 인터페이스를 생성하고 구성 하므로, 따로 Bridge 인터페이스를 생성하기 보다는, Docker 데몬이 실행 될때, Flannel의 CIDR로 강제로 사용하기 위한 설정을 해야합니다.

따라서, docker0 인터페이스를 초기화 하고, Docker 데몬 옵션을 추가하여 Docker를 실행토록 합니다.
실행 중인 Docker를 중지하고, docker0 인터페이스를 삭제 합니다.

root@kubernetes-master:~# service docker stop
root@kubernetes-master:~# ip link set dev docker0 down
root@kubernetes-master:~# brctl delbr docker0

Flannel의 CIDR을 확인 합니다.

root@kubernetes-master:~# ip a s | grep flannel.1 | grep inet
    inet 10.0.56.0/16 scope global flannel.1

이후 Docker의 데몬 옵션 파일을 열어 –bip 옵션을 추가 합니다.

root@kubernetes-master:~# nano /etc/default/docker
root@kubernetes-master:~# DOCKER_OPTS="--bip=10.0.56.1/24--dns 8.8.8.8 --dns 8.8.4.4"

Docker를 시작 합니다.

root@kubernetes-master:~# service docker start


– Kube Proxy

Master의 IP와 포트를 지정 하여 실행 합니다.

kubernetes-minion-0

root@kubernetes-minion-0:~# kube-proxy \
--master=172.17.1.4:8080 \
--v=0 > /var/log/k8s-proxy.log 2>&1 &

kubernetes-minion-1

root@kubernetes-minion-1:~# kube-proxy \
--master=172.17.1.4:8080 \
--v=0 > /var/log/k8s-proxy.log 2>&1 &


– Kubelet

외부에서 연결이 가능하도록 public(0.0.0.0)으로 binding 합니다.
(이것 역시 내부로 사용할 경우 내부 IP로 지정 해주시면 됩니다.)

그리고, API Server의 IP와 포트를 지정 해주고 실행 합니다.
(필요에 따라, kubelet, cadvisor 포트를 지정 하여 실행 해주어도 됩니다.)

kubernetes-minion-0

root@kubernetes-minion-0:~# kubelet \
--port=10250 \
--address=0.0.0.0 \
--cadvisor-port=4194 \
--api-servers=172.17.1.4:8080 \
--hostname-override="$(ip a s | grep 'eth0' | grep 'inet' | cut -d '/' -f 1 | awk '{ print $2 }')" \
--v=0 > /var/log/k8s-kubelet.log 2>&1 &

 

kubernetes-minion-1

root@kubernetes-minion-1:~# kubelet \
--port=10250 \
--address=0.0.0.0 \
--cadvisor-port=4194 \
--api-servers=172.17.1.4:8080 \
--hostname-override="$(ip a s | grep 'eth0' | grep 'inet' | cut -d '/' -f 1 | awk '{ print $2 }')" \
--v=0 > /var/log/k8s-kubelet.log 2>&1 &

 

 

Kubernetes – Client (kubectl)


관리자가 kubectl 명령어 도구를 통해 Pod, Label, Replication Controller를 추가/수정 할 수 있습니다.

– Create
Create는 YAML 형식의 파일을 통해 Pod, Label을 직접 지정하여 만들 수 있는 명령어 입니다.
예를 들어 ngnx를 10개 실행 하고자 할 경우 아래와 같이 지정 해주시면 됩니다.

root@kubernetes-client:~# nano nginx.yaml
apiVersion: v1
kind: ReplicationController
metadata:
 name: nginxs
spec:
 replicas: 10
 template:
 metadata:
 labels:
 app: nginx
 spec:
 containers:
 - name: nginx-single
 image: ruo91/nginx:latest
 ports:
 - containerPort: 80
root@kubernetes-client:~# kubectl create -f nginx.yaml -s 172.17.1.4:8080
replicationcontroller "nginxs" created

위의 옵션 중 -s 는 API의 서버를 뜻합니다.

명령이 실행이 되고 나면, 모든 Minion들은 Docker Hub 저장소를 통해 ruo91 사용자의 nginx 이미지를 다운로드 합니다.
이후 Minion들 중에 Workload가 낮은 서버에서 해당 Container가 실행 됩니다.

 

– GET
get 명령어는 자원 정보를 확인 할 때 사용합니다.
Pod의 정보를 확인 하고자 할 경우에는 아래와 같이 사용 하시면 됩니다.

root@kubernetes-client:~# kubectl get pods -s 172.17.1.4:8080
NAME           READY     STATUS    RESTARTS   AGE
nginxs-1dzwr   1/1       Running   0          1m
nginxs-2kq2o   1/1       Running   0          1m
nginxs-6ph77   1/1       Running   0          1m
nginxs-6wxx8   1/1       Running   0          1m
nginxs-98rsw   1/1       Running   0          1m
nginxs-n5gks   1/1       Running   0          1m
nginxs-odo7u   1/1       Running   0          1m
nginxs-p7oc2   1/1       Running   0          1m
nginxs-ubpyl   1/1       Running   0          1m
nginxs-utanv   1/1       Running   0          1m

 

– Describe
특정 자원에 대해 자세한 정보를 확인 할 때 사용합니다.

root@kubernetes-client:~# kubectl describe -f nginx.yaml -s 172.17.1.4:8080
Name:           nginxs
Namespace:      default
Image(s):       ruo91/nginx:latest
Selector:       app=nginx
Labels:         app=nginx
Replicas:       10 current / 10 desired
Pods Status:    10 Running / 0 Waiting / 0 Succeeded / 0 Failed
No volumes.
Events:
  FirstSeen     LastSeen        Count   From                            SubobjectPath   Reason                  Message
  ─────────     ────────        ─────   ────                            ─────────────   ──────                  ───────
  44m           44m             1       {replication-controller }                       SuccessfulCreate        Created pod: nginxs-n5gks
  44m           44m             1       {replication-controller }                       SuccessfulCreate        Created pod: nginxs-6wxx8
  44m           44m             1       {replication-controller }                       SuccessfulCreate        Created pod: nginxs-98rsw
  44m           44m             1       {replication-controller }                       SuccessfulCreate        Created pod: nginxs-6ph77
  44m           44m             1       {replication-controller }                       SuccessfulCreate        Created pod: nginxs-ubpyl
  44m           44m             1       {replication-controller }                       SuccessfulCreate        Created pod: nginxs-odo7u
  44m           44m             1       {replication-controller }                       SuccessfulCreate        Created pod: nginxs-1dzwr
  44m           44m             1       {replication-controller }                       SuccessfulCreate        Created pod: nginxs-utanv
  44m           44m             1       {replication-controller }                       SuccessfulCreate        Created pod: nginxs-2kq2o
  44m           44m             1       {replication-controller }                       SuccessfulCreate        Created pod: nginxs-p7oc2

 

– Log
해당 Pod에 존재하는 Container의 로그를 확인 할때 사용합니다.
이후 log 명령어를 통해 로그 확인이 가능 합니다.

root@kubernetes-client:~# kubectl logs nginxs-n5gks -s 172.17.1.4:8080
/usr/lib/python2.7/dist-packages/supervisor/options.py:295: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
  'Supervisord is running as root and it is searching '
2015-11-01 13:24:47,259 CRIT Supervisor running as root (no user in config file)
2015-11-01 13:24:47,265 WARN Included extra file "/etc/supervisor/conf.d/supervisord.conf" during parsing
2015-11-01 13:24:47,472 INFO RPC interface 'supervisor' initialized
2015-11-01 13:24:47,472 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2015-11-01 13:24:47,472 INFO supervisord started with pid 1
2015-11-01 13:24:48,883 INFO spawned: 'nginx' with pid 8
2015-11-01 13:24:49,074 DEBG fd 7 closed, stopped monitoring <POutputDispatcher at 140246775453672 for <Subprocess at 140246775692752 with name nginx in state STARTING> (stdout)>
2015-11-01 13:24:49,075 INFO exited: nginx (exit status 0; not expected)
2015-11-01 13:24:49,075 DEBG received SIGCLD indicating a child quit
2015-11-01 13:24:50,078 INFO spawned: 'nginx' with pid 16
2015-11-01 13:24:50,248 DEBG fd 7 closed, stopped monitoring <POutputDispatcher at 140246775453888 for <Subprocess at 140246775692752 with name nginx in state STARTING> (stdout)>
2015-11-01 13:24:50,248 INFO exited: nginx (exit status 1; not expected)
2015-11-01 13:24:50,248 DEBG received SIGCLD indicating a child quit
2015-11-01 13:24:52,319 INFO spawned: 'nginx' with pid 22
2015-11-01 13:24:52,415 DEBG fd 7 closed, stopped monitoring <POutputDispatcher at 140246775453960 for <Subprocess at 140246775692752 with name nginx in state STARTING> (stdout)>
2015-11-01 13:24:52,432 INFO exited: nginx (exit status 1; not expected)
2015-11-01 13:24:52,432 DEBG received SIGCLD indicating a child quit
2015-11-01 13:24:55,508 INFO spawned: 'nginx' with pid 28
2015-11-01 13:24:55,657 DEBG fd 7 closed, stopped monitoring <POutputDispatcher at 140246775454032 for <Subprocess at 140246775692752 with name nginx in state STARTING> (stdout)>
2015-11-01 13:24:55,668 INFO exited: nginx (exit status 1; not expected)
2015-11-01 13:24:55,670 DEBG received SIGCLD indicating a child quit
2015-11-01 13:24:56,672 INFO gave up: nginx entered FATAL state, too many start retries too quickly

 

 

– Stop
특정 Container를 중지 시킬 수 있습니다. 이 명령어를 통해 강제로 장애 발생을 시킬 수 있습니다.

kubectl stop (-f FILENAME | RESOURCE (ID | -l label | --all)) [flags]

 

Pod 중에 nginxs-1m3ns 이름을 가진 것을 중지 시켜 보도록 하겠습니다.

root@kubernetes-client:~# kubectl stop pods nginxs-n5gks -s 172.17.1.4:8080
pod "nginxs-n5gks" deleted<br>

 

위 명령어가 실행 되면 replicas 수에 맞춰 새로운 Container를 실행하고 Pod 이름이 변경 되어 나타 납니다.

I1101 13:44:12.693732    1785 kubelet.go:2008] SyncLoop (UPDATE): "nginxs-n5gks_default"
I1101 13:44:12.746609    1785 manager.go:1404] Killing container "58c245e0360ff2ebf8e5b3ea9d8fa0e42838fceaf41a0c1a64a31b7e3b40a18c nginx-single default/nginxs-n5gks" with 30 second grace period
I1101 13:44:12.953058    1785 manager.go:1438] Container "58c245e0360ff2ebf8e5b3ea9d8fa0e42838fceaf41a0c1a64a31b7e3b40a18c nginx-single default/nginxs-n5gks" exited after 206.394222ms
W1101 13:44:12.953106    1785 manager.go:1444] No ref for pod '"58c245e0360ff2ebf8e5b3ea9d8fa0e42838fceaf41a0c1a64a31b7e3b40a18c nginx-single default/nginxs-n5gks"'
I1101 13:44:12.954684    1785 manager.go:1404] Killing container "dad51f944cdd780fbb91ccee704b64acb44b97d86d2b64da0f3cfa3ed789fe49 default/nginxs-n5gks" with 30 second grace period
I1101 13:44:13.146777    1785 manager.go:1438] Container "dad51f944cdd780fbb91ccee704b64acb44b97d86d2b64da0f3cfa3ed789fe49 default/nginxs-n5gks" exited after 192.039838ms
W1101 13:44:13.146826    1785 manager.go:1444] No ref for pod '"dad51f944cdd780fbb91ccee704b64acb44b97d86d2b64da0f3cfa3ed789fe49 default/nginxs-n5gks"'
I1101 13:44:12.792583    1928 kubelet.go:2005] SyncLoop (ADD): "nginxs-psb95_default"
I1101 13:44:12.796750    1928 manager.go:1707] Need to restart pod infra container for "nginxs-psb95_default" because it is not found
I1101 13:44:13.382160    1928 hairpin.go:49] Unable to find pair interface, setting up all interfaces: exec: "ethtool": executable file not found in $PATH
I1101 13:44:13.389841    1928 provider.go:91] Refreshing cache for provider: *credentialprovider.defaultDockerConfigProvider
I1101 13:44:13.390157    1928 docker.go:159] Pulling image ruo91/nginx:latest without credentials

새로 추가 된 nginxs-psb95 가 있는지 확인 해봅니다.

root@kubernetes-client:~# kubectl get pods -s 172.17.1.4:8080
NAME           READY     STATUS    RESTARTS   AGE
nginxs-1dzwr   1/1       Running   0          5m
nginxs-2kq2o   1/1       Running   0          5m
nginxs-6ph77   1/1       Running   0          5m
nginxs-6wxx8   1/1       Running   0          5m
nginxs-98rsw   1/1       Running   0          5m
nginxs-odo7u   1/1       Running   0          5m
nginxs-p7oc2   1/1       Running   0          5m
nginxs-psb95   1/1       Running   0          2m
nginxs-ubpyl   1/1       Running   0          5m
nginxs-utanv   1/1       Running   0          5m

 

Kubernetes – Web UI


API Server를 실행하면 기본값인 8080 포트를 통해 WEB UI를 지원합니다.

이전 v0.x 에서는 Web UI가 API Server에 자체 내장 되어 있었지만, v1.x 버전부터 Web UI(kube-ui)가 Minion 서버에 Pod로 실행 되어 API Server와 연결 되므로, kubectl 명령어를 통해 몇가지 작업이 필요 합니다.

우선, client 서버에서 kube-ui의 yaml 파일 2개를 생성 합니다.

– kube-ui-rc.yaml
https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/kube-ui/kube-ui-rc.yaml

root@kubernetes-client:~# cat > /opt/kube-ui-rc.yaml << EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: kube-ui-v3
  namespace: kube-system
  labels:
    k8s-app: kube-ui
    version: v3
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 1
  selector:
    k8s-app: kube-ui
    version: v3
  template:
    metadata:
      labels:
        k8s-app: kube-ui
        version: v3
        kubernetes.io/cluster-service: "true"
    spec:
      containers:
      - name: kube-ui
        image: gcr.io/google_containers/kube-ui:v3
        resources:
          limits:
            cpu: 100m
            memory: 50Mi
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 30
          timeoutSeconds: 5
EOF


– kube-ui-svc.yaml
https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/kube-ui/kube-ui-svc.yaml

root@kubernetes-client:~# cat > /opt/kube-ui-svc.yaml << EOF
apiVersion: v1
kind: Service
metadata:
  name: kube-ui
  namespace: kube-system
  labels:
    k8s-app: kube-ui
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeUI"
spec:
  selector:
    k8s-app: kube-ui
  ports:
  - port: 80
    targetPort: 8080
EOF

이후 kube-ui Pod를 생성 합니다.

root@kubernetes-client:~# kubectl create -f /opt/kube-ui-rc.yaml --namespace=kube-system -s 172.17.1.4:8080"
root@kubernetes-client:~# kubectl create -f /opt/kube-ui-svc.yaml --namespace=kube-system -s 172.17.1.4:8080"

웹서버를 사용 중이라면, Reverse Proxy 설정을 합니다.

root@nginx:~# cat > /etc/nginx/sites-enabled/kubernetes.conf << EOF
# Kubernetes Web UI
server {
	listen 80;
	server_name kubernetes.example.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:8080;
		client_max_body_size 10M;
	}
}
EOF
root@nginx:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@nginx:~# nginx -s reload

해당 도메인으로 접속하여 살펴 봅니다.

http://kubernetes.example.net/ui/

k8s_web_ui_0

k8s_web_ui_1
k8s_web_ui_2
k8s_web_ui_3
k8s_web_ui_4

참고

– Google I/O 2014 – Containerizing the Cloud with Docker on Google Cloud Platform
https://www.youtube.com/watch?v=tsk0pWf4ipw

– Connecting Containers: Building a PaaS with Docker and Kubernetes
https://www.youtube.com/watch?v=omTGY8LjVdA

– Github GoogleCloudPlatform
https://github.com/GoogleCloudPlatform/kubernetes/blob/master/DESIGN.md

– Slideshare
http://www.slideshare.net/search/slideshow?searchfrom=header&q=kubernetes