How-to setup Kubernetes to manage Docker Cluster on ubuntu

什麼是 Kubernetes

Kubernetes 是來自 Google 雲平臺的開源容器集羣管理系統。基於 Docker 構建一個容器的調度服務。該系統可以自動在一個容器集羣中選擇一個工作容器供使用。其核心概念是 Container Pod。詳細的設計思路請參考這裏

關於 Kubernetes 系統架構及組件介紹見 這裏

本文通過實際操作來演示Kubernetes的使用,主要包括如下內容:

  • 部署環境介紹,以及Kubernetes集羣邏輯架構

  • 安裝部署Open vSwitch跨機器容器通信工具

  • 安裝部署Etcd和Kubernetes的各大組件

  • 演示Kubernetes管理容器和服務

部署環境及架構
  • 操作系統: ubuntu 14.04 x86_64

  • Kubernetes: v1.0.1

  • Etcd版本: 3.0.0

  • Docker版本: 1.6.2

  • Open vSwith版本: 2.0.2

  • 主機信息

  • 服務器信息:

  • Role         service                                  Hostname         IP Address
    master       Kube-APIServer kubelet proxy etcd        lucy.suzf.net    172.16.9.86
    Minion1      kubelet proxy open-switch docker         eva.suzf.net     172.16.9.10
    Minion2      kubelet proxy open-switch docker         cali.suzf.net    172.16.9.20


在詳細介紹部署Kubernetes集羣前,先給大家展示下集羣的邏輯架構。從下圖可知,整個系統分爲兩部分,第一部分是Kubernetes APIServer,是整個系統的核心,承擔集羣中所有容器的管理工作;第二部分是minion,運行Container Daemon,是所有容器棲息之地,同時在minion上運行Open vSwitch程序,通過GRE Tunnel負責minions之間Pod的網絡通信工作。

k8s

http://suzf.net 純手工鍛造 歡迎關注與交流  ^_^
安裝Open vSwitch及配置GRE

爲了解決跨minion之間Pod的通信問題,我們在每個minion上安裝Open vSwtich,並使用GRE或者VxLAN使得跨機器之間P11od能相互通信,本文使用GRE,而VxLAN通常用在需要隔離的大規模網絡中。對於 Open vSwitch的介紹請參考另一篇文章Open vSwitch。

[ both minion ]
sudo apt-get install openvswitch-switch bridge-utils -y

安裝完Open vSwitch和橋接工具後,接下來便建立minion節點之間的隧道。
首先在所有minion上分別建立OVS Bridge:

sudo ovs-vsctl add-br obr0

接下來建立gre,並將新建的gre0添加到obr0

# minion1
sudo ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=172.16.3.20

# minion2
sudo ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=172.16.3.10

至此,minion1和minion2之間的隧道已經建立。然後我們在minion1和minion2上創建Linux網橋kbr0替代 Docker默認的docker0(我們假設minion1和minion2都已安裝Docker),設置minion1的kbr0的地址爲 172.17.1.1/24, minion2的kbr0的地址爲172.17.2.1/24,並添加obr0爲kbr0的接口,以下命令在minion1和minion2上執行:

[ both minion ]
# sudo brctl addbr kbr0               # 創建linux bridge代替docker0
# sudo brctl addif kbr0 obr0          # 添加obr0爲kbr0的接口
# # sudo ip link set dev obr0 up        # 設置obr0爲up狀態
# sudo ip link set dev docker0 down   # 設置docker0爲down狀態
# sudo ip link del dev docker0        # 刪除docker0,可選

查看這些接口的狀態

# service openvswitch-switch status
openvswitch-switch start/running
@eva:~# ovs-vsctl show
52c65487-12fc-4228-b2ee-7c5ba409d8d2
    Bridge "obr0"
        Port "gre0"
            Interface "gre0"
                type: gre
                options: {remote_ip="172.16.3.20"}
        Port "obr0"
            Interface "obr0"
                type: internal
    ovs_version: "2.0.2"

@eva:~#  brctl show
bridge name    bridge id        STP enabled    interfaces
kbr0        8000.de14d8a90948    no        obr0

爲了使新建的kbr0在每次系統重啓後任然有效,我們在minion1的/etc/network/interfaces文件中
追加內容如下:(在CentOS上會有些不一樣)

@eva:~# tail -9  /etc/network/interfaces 

auto kbr0
iface kbr0 inet static
    address 172.16.1.1
    netmask 255.255.255.0
    # gateway 172.16.1.0
    # dns-nameservers 172.31.1.1
    up route add 172.16.2.0/24 via 172.16.3.20 dev eth0
    down route add 172.16.2.0/24 via 172.16.3.20 dev eth0

minion2 網卡配置類似 。然後 啓動虛擬網絡接口

sudo ip link set dev obr0 up

你能在minion1和minion2上發現kbr0都設置了相應的IP地址。
這是我們創建的隧道還不能通信。經查找這是因爲在minion1和minion2上缺少訪問172.17.2.1和172.17.1.1的路由,因此我們需要添加路由保證彼此之間能通信:

# minion1 上執行
sudo ip route add 172.16.2.0/24 via 172.16.3.20 dev eth0

# minion2 上執行
sudo ip route add 172.16.1.0/24 via 172.16.3.10 dev eth0

現在網絡之間可以正常通信了

@eva:~# ping 172.16.2.1 -c 2
PING 172.16.2.1 (172.16.2.1) 56(84) bytes of data.
64 bytes from 172.16.2.1: icmp_seq=1 ttl=64 time=0.714 ms
64 bytes from 172.16.2.1: icmp_seq=2 ttl=64 time=0.337 ms

--- 172.16.2.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.337/0.525/0.714/0.189 ms


@cali:~# ping 172.16.1.1 -c 2
PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data.
64 bytes from 172.16.1.1: icmp_seq=1 ttl=64 time=0.577 ms
64 bytes from 172.16.1.1: icmp_seq=2 ttl=64 time=0.269 ms

--- 172.16.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.269/0.423/0.577/0.154 ms

Minion 節點安裝 docker

[ both minion ]
sudo apt-get install docker.io -y

修改docker默認橋接網橋,並重啓

sudo vi /etc/default/docker
DOCKER_OPTS="-b kbr0"

sudo service docker restart
Etcd  安裝與配置

etcd是一個開源的用於配置共享和服務發現的高性能的鍵值存儲系統。

注意:創建存放所有組件二進制文件目錄,最好是/opt/bin目錄,因爲啓動腳本里面寫的就是這個目錄。

@lucy:~# cd /usr/local/src/
@lucy:/usr/local/src#sudo wget https://github.com/coreos/etcd/releases/download/v3.0.0/etcd-v3.0.0-linux-amd64.tar.gz
tar xf etcd-v3.0.0-linux-amd64.tar.gz
cd etcd-v3.0.0-linux-amd64/
mkdir /opt/bin
cp -a etcd etcdctl /opt/bin

etcd官方建議使用新的2379端口代替4001

cat >  /etc/default/etcd << EOF
ETCD_OPTS="\\
--listen-client-urls http://0.0.0.0:4001 \\
--advertise-client-urls http://0.0.0.0:4001 \\
--data-dir /var/lib/etcd/default.etcd"
EOF


# 選項說明:
--listen-peer-urls :etcd作爲分佈式節點通信端口,默認指定端口7001,我們這裏做的是單節點,這個參數可以不寫,需要知道的是v2版本中改變爲2380,7001仍可用
--listen-client-urls :客戶端操作etcd API的端口,默認指定端口4001,v2中改變爲2379,在k8s中我們要使用4001端口
--data-dir :指定數據存放目錄
--advertise-client-urls :作爲分佈式的客戶端連接端口,如果不寫這個參數會出現以下報錯

etcdmain: error verifying flags, -advertise-client-urls is required when -listen-client-urls is set explicitly. See 'etcd --help'.
etcdmain: When listening on specific address(es), this etcd process must advertise accessible url(s) to each connected client.

etcd服務配置好後先不啓動,待會用下面kubernetes提供的啓動腳本啓動! one key start  cool ~ ~~

下面安裝 Kubernetes APIServer 及kubelet、proxy 等服務。

安裝Kubernetes APIServer
下載安裝kubernetes各組件

可以自己從源碼編譯kubernetes(需要安裝golang環境),也可以從GitHub Kubernetes repo release page.選擇源碼包v1.0.1版本下載。

@lucy:~# cd /usr/local/src/
@lucy:/usr/local/src#sudo wget https://github.com/coreos/etcd/releases/download/v3.0.0/etcd-v3.0.0-linux-amd64.tar.gz
@lucy:/usr/local/src#sudo wget https://github.com/GoogleCloudPlatform/kubernetes/releases/download/v1.0.1/kubernetes.tar.gz

然後解壓下載的kubernetes和etcd包,並在kubernetes(minion1)、minion2上創建目錄/opt/bin

[ All nodes ]
# mkdir /opt/bin
# echo "export PATH=\$PATH:/opt/bin" >> /etc/profile
# source /etc/profile

解壓kubernetes

tar xf kubernetes.tar.gz
cd kubernetes/server && tar xf kubernetes-server-linux-amd64.tar.gz
cd kubernetes/server/bin/

APIserver本身需要的是kube-apiserver kube-scheduler kube-controller-manager kubecfg四個

@lucy #cp kube-apiserver kube-scheduler kube-controller-manager kubecfg  /opt/bin/

把proxy和kubelet複製到其他minions,確保這些文件都是可執行的

scp kube-proxy kubelet [email protected]:/opt/bin
scp kube-proxy kubelet [email protected]:/opt/bin

拷貝相關組件啓動腳本

cd /usr/local/src/kubernetes/cluster/ubuntu
@lucy:/usr/local/src/kubernetes/cluster/ubuntu# cp master/init_scripts/* /etc/init.d/
@lucy:/usr/local/src/kubernetes/cluster/ubuntu# cp master/init_conf/* /etc/init/

配置kube*啓動選項

# kube-apiserver
cat > /etc/default/kube-apiserver << EOF
KUBE_APISERVER_OPTS="--address=0.0.0.0 \\
--port=8080 \\
--etcd_servers=http://127.0.0.1:4001 \\
--logtostderr=true \\
--portal_net=172.16.9.0/24"
EOF
# 選項說明:
--insecure-bind-address:api監聽地址
--insecure-port:api監聽端口
--service-cluster-ip-range:上面說到service角色是定義集羣中一個pod集合,這個pod中容器提供一種服務,當創建service時會分配一個CLUSTER_IP提供統一的訪問入口,那麼,這個選項就是指定分配的IP範圍
--etcd_servers:指定etcd連接地址


# kube-scheduler
cat > /etc/default/kube-scheduler << EOF
KUBE_SCHEDULER_OPTS="--master=127.0.0.1:8080 \\
--logtostderr=true"
EOF

# kube-controller-manager
cat > /etc/default/kube-controller-manager << EOF
KUBE_CONTROLLER_MANAGER_OPTS="--master=127.0.0.1:8080 \\
--logtostderr=true"
EOF

Minion 配置

* 複製kubelet、kube-proxy等到 minion1:
@lucy:/usr/local/src/kubernetes/cluster/ubuntu# scp minion/init_scripts/kube*  172.16.9.10:/etc/init.d/
@lucy:/usr/local/src/kubernetes/cluster/ubuntu# scp minion/init_conf/{kubelet,kube-proxy}.conf 172.16.9.10:/etc/init/

# 注意:ubuntu默認禁止root遠程登錄,需要配置允許ssh登錄,也可以先將二進制包拷貝到minion服務器能ssh登錄的用戶,然後再sudo移動到/opt/bin目錄

* 在 minion1 端進行
cat> /etc/default/kubelet << EOF
KUBELET_OPTS="--address=0.0.0.0 \\
--port=10250 \\
--hostname_override=172.16.3.10 \\
--api_servers=http://172.16.3.100:8080 \\
--pod-infra-container-image=docker.io/kubernetes/pause:latest \\
--logtostderr=true"
EOF

選項說明
--hostname_override:在master端顯示的節點名稱,對應的minion主機修改對應的IP
--pod-infra-container-image:創建pod時下載鏡像地址,默認是gcr.io/google_containers/pause:0.8.0,需要***才能訪問,所以指定了官方鏡像下載源

cat> /etc/default/kube-proxy << EOF
KUBE_PROXY_OPTS="--master=http://172.16.3.100:8080 \\
--logtostderr=true"
EOF

# (對 minion2 重複上面 * 兩個步驟,把上面.10改成.20)

所有配置就緒,Launch

@lucy:~# service  etcd start
etcd start/running, process 4030

# 注意:如果etcd啓動後進程不存在,嘗試去掉/etc/init.d/etcd第64行的 >> $ETCD_LOGFILE 2>&1追加日誌這部分再啓動試試。

@lucy:~# /etc/init.d/kube-apiserver start
 * Kube-Apiserver is managed via upstart, try using service kube-apiserver start

What are you 弄啥嘞? 查看一下etcd 的啓動腳本 發現少一個判斷
@lucy:~# sed -n '36,39'p /etc/init.d/etcd 
# see also init_is_upstart in /lib/lsb/init-functions (which isn't available in Ubuntu 12.04, or we'd use it)
if false && [ -x /sbin/initctl ] && /sbin/initctl version 2>/dev/null | grep -q upstart; then
log_failure_msg "$ETCD_DESC is managed via upstart, try using service $BASE $1"
exit 1
@lucy:~# sed -n '36,39'p /etc/init.d/kube-apiserver 
# see also init_is_upstart in /lib/lsb/init-functions (which isn't available in Ubuntu 12.04, or we'd use it)
if [ -x /sbin/initctl ] && /sbin/initctl version 2>/dev/null | grep -q upstart; then
log_failure_msg "$KUBE_APISERVER_DESC is managed via upstart, try using service $BASE $1"
exit 1

加上判斷在試一試, 呵呵  好了~
@lucy:~# service kube-apiserver  start
kube-apiserver start/running, process 4222

kube-apiserver啓動後會自動運行kube-scheduler、kube-controller-manager

這些服務的日誌可以從/var/log/upstart/中找到。
lucy:~# ls /var/log/upstart/kube-*
/var/log/upstart/kube-apiserver.log  /var/log/upstart/kube-controller-manager.log  /var/log/upstart/kube-scheduler.log

可以通過etcdctl查看到etcd存儲着關於集羣的各種信息

@lucy:~# etcdctl ls /registry
/registry/minions
/registry/namespaces
/registry/pods
/registry/ranges
/registry/serviceaccounts
/registry/services
/registry/controllers
/registry/events

啓動 minion 節點 服務

[ both minion ]
# service kube-proxy start
# service kubelet start

到這 kubernetes 就配置完了,查看下集羣節點:

k8s_pods_info

kubernetes常用命令

# kubectl get nodes                       # 查查看minion主機
# kubectl get pods                        # 查看pods清單
# kubectl get services                    # 查看service清單
# kubectl get services -o json            # 查看service清單 以 json 形式輸出
# kubectl get replicationControllers      # 查看replicationControllers清單
# for i in `kubectl get pod|tail -n +2|awk '{print $1}'`; do kubectl delete pod $i; done   #刪除所有pods

或者通過Server api for REST方式(推薦,及時性更高)

kubernetes 測試

命令啓動一個nginx:

# kubectl run --image=nginx nginx-test-by-suzf-net
replicationcontroller "nginx-test-by-suzf-net" created

初次創建要下載鏡像,需等待數分鐘,查看集羣pods:

# kubectl get pods
NAME                           READY     STATUS    RESTARTS   AGE
nginx-test-by-suzf-net-uepzq   1/1       Running   0          8h

使用yaml 文件創建 pod

root@lucy:~# cat nginx-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
    name: nginx
    labels:
        app: nginx
spec:
    containers:
        - name: nginx
          image: nginx
          ports:
              - containerPort: 80


root@lucy:~# kubectl create -f nginx-pod.yaml
pods/nginx
root@lucy:~# kubectl get pod
NAME                         READY STATUS   RESTARTS AGE
nginx                        1/1   Running  0        29s
nginx-test-by-suzf-net-uepzq 1/1   Running  0        8h

查看下創建的nginx信息

k8s_pod_info

訪問一下 試試

k8s_nginx_access

當然我們也可以使用Kubernetes提供的例子Guestbook(下載的源碼example目錄下可以找到)來做測試。

至此,kubernetes集羣就部署成功了。歡迎繼續關注 ^_^.


參考文檔
http://kubernetes.io/docs/getting-started-guides/ubuntu/
http://lizhenliang.blog.51cto.com/7876557/1736572
http://blog.liuts.com/post/247/
https://segmentfault.com/a/1190000002620961


 License:Attribution-NonCommercial-NoDerivatives 4.0 International
 本文出自 Suzf Blog。 如未註明,均爲 SUZF.NET 原創。
 轉載請註明出處:http://suzf.net/thread-0702-951.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章