CentOS 7實戰Kubernetes部署
1. 前言
上一節我們闡述了Kubernetes的系統架構,讓大家對Kubernetes有一定的初步瞭解,但是就如何使用Kubernetes, 也許大家還不知如何下手。本文作者將帶領大家如何在本地部署、配置Kubernetes叢集網路環境以及通過例項演示跨機器服務間的通訊,主要包括如下內容:
- 部署環境介紹
- Kubernetes叢集邏輯架構
- 部署Open vSwitch、Kubernetes、Etcd元件
- 演示Kubernetes管理容器
2. 部署環境
- VMware Workstation:10.0.3
- VMware Workstation網路模式:NAT
- 作業系統資訊:CentOS 7 64位
- Open vSwitch版本資訊:2.3.0
- Kubernetes版本資訊:0.5.2
- Etcd版本資訊:0.4.6
- Docker版本資訊:1.3.1
- 伺服器資訊:
| Role | Hostname | IP Address | |:---------:|:----------:|:----------: | |APIServer |kubernetes |192.168.230.3| |Minion | minion1 |192.168.230.4| |Minion | minion2 |192.168.230.5|
3. Kubernetes叢集邏輯架構
在詳細介紹部署Kubernetes叢集前,先給大家展示下叢集的邏輯架構。從下圖可知,整個系統分為兩部分,第一部分是Kubernetes APIServer,是整個系統的核心,承擔叢集中所有容器的管理工作;第二部分是minion,執行Container Daemon,是所有容器棲息之地,同時在minion上執行Open vSwitch程式,通過GRE Tunnel負責minion之間Pod的網路通訊工作。
4. 部署Open vSwitch、Kubernetes、Etcd元件
4.1 安裝Open vSwitch及配置GRE
為了解決跨minion之間Pod的通訊問題,我們在每個minion上安裝Open vSwtich,並使用GRE或者VxLAN使得跨機器之間Pod能相互通訊,本文使用GRE,而VxLAN通常用在需要隔離的大規模網路中。對於Open vSwitch的具體安裝步驟,可參考這篇部落格,我們在這裡就不再詳細介紹安裝步驟了。安裝完Open vSwitch後,接下來便建立minion1和minion2之間的隧道。首先在minion1和minion2上建立OVS Bridge,
[root@minion1 ~]# ovs-vsctl add-br obr0
接下來建立gre,並將新建的gre0新增到obr0,在minion1上執行如下命令,
[root@minion1 ~]# ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=192.168.230.5
在minion2上執行,
[root@minion2 ~]# ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=192.168.230.4
至此,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上執行。
[root@minion1 ~]# brctl addbr kbr0 //建立linux bridge [root@minion1 ~]# brctl addif kbr0 obr0 //新增obr0為kbr0的介面 [root@minion1 ~]# ip link set dev docker0 down //設定docker0為down狀態 [root@minion1 ~]# ip link del dev docker0 //刪除docker0
為了使新建的kbr0在每次系統重啟後任然有效,我們在/etc/sysconfig/network-scripts/目錄下新建minion1的ifcfg-kbr0如下:
DEVICE=kbr0 ONBOOT=yes BOOTPROTO=static IPADDR=172.17.1.1 NETMASK=255.255.255.0 GATEWAY=172.17.1.0 USERCTL=no TYPE=Bridge IPV6INIT=no
同樣在minion2上新建ifcfg-kbr0,只需修改ipaddr為172.17.2.1和gateway為172.17.2.0即可,然後執行systemctl restart network重啟系統網路服務,你能在minion1和minion2上發現kbr0都設定了相應的IP地址。為了驗證我們建立的隧道是否能通訊,我們在minion1和minion2上相互ping對方kbr0的IP地址,從下面的結果發現是不通的,經查詢這是因為在minion1和minion2上缺少訪問172.17.1.1和172.17.2.1的路由,因此我們需要新增路由保證彼此之間能通訊。
[root@minion1 network-scripts]# ping 172.17.2.1 PING 172.17.2.1 (172.17.2.1) 56(84) bytes of data. ^C --- 172.17.2.1 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 1000ms [root@minion2 ~]# ping 172.17.1.1 PING 172.17.1.1 (172.17.1.1) 56(84) bytes of data. ^C --- 172.17.1.1 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 1000ms
由於通過ip route add新增的路由會在下次系統重啟後失效,為此我們在/etc/sysconfig/network-scripts目錄下新建一個檔案route-eth0儲存路由,這裡需要注意的是route-eth0和ifcfg-eth0的黑體部分必須保持一致,否則不能工作,這樣新增的路由在下次重啟後不會失效。為了保證兩臺minion的kbr0能相互通訊,我們在minion1的route-eth0裡新增路由172.17.2.0/24 via 192.168.230.5 dev eno16777736,eno16777736是minion1的網路卡,同樣在minion2的route-eth0裡新增路由172.17.1.0/24 via 192.168.230.4 dev eno16777736。重啟網路服務後再次驗證,彼此kbr0的地址可以ping通,如:
[root@minion2 network-scripts]# ping 172.17.1.1 PING 172.17.1.1 (172.17.1.1) 56(84) bytes of data. 64 bytes from 172.17.1.1: icmp_seq=1 ttl=64 time=2.49 ms 64 bytes from 172.17.1.1: icmp_seq=2 ttl=64 time=0.512 ms ^C --- 172.17.1.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 0.512/1.505/2.498/0.993 ms
到現在我們已經建立了兩minion之間的隧道,而且能正確的工作。下面我們將介紹如何安裝Kubernetes APIServer及kubelet、proxy等服務。
4.2 安裝Kubernetes APIServer
在安裝APIServer之前,我們先下載Kubernetes及Etcd,做一些準備工作。在kubernetes上的具體操作如下:
[root@kubernetes ~]# mkdir /tmp/kubernetes [root@kubernetes ~]# cd /tmp/kubernetes/ [root@kubernetes kubernetes]# wget https://github.com/GoogleCloudPlatform/kubernetes/releases/download/v0.5.2/kubernetes.tar.gz [root@kubernetes kubernetes]# wget https://github.com/coreos/etcd/releases/download/v0.4.6/etcd-v0.4.6-linux-amd64.tar.gz
然後解壓下載的kubernetes和etcd包,並在kubernetes、minion1、minion2上建立目錄/opt/kubernetes/bin,
[root@kubernetes kubernetes]# mkdir -p /opt/kubernetes/bin [root@kubernetes kubernetes]# tar xf kubernetes.tar.gz [root@kubernetes kubernetes]# tar xf etcd-v0.4.6-linux-amd64.tar.gz [root@kubernetes kubernetes]# cd ~/kubernetes/server [root@kubernetes server]# tar xf kubernetes-server-linux-amd64.tar.gz [root@kubernetes kubernetes]# /tmp/kubernetes/kubernetes/server/kubernetes/server/bin
複製kube-apiserver,kube-controller-manager,kube-scheduler,kubecfg到kubernetes的/opt/kubernetes/bin目錄下,而kubelet,kube-proxy則複製到minion1和minion2的/opt/kubernetes/bin,並確保都是可執行的。
[root@kubernetes amd64]# cp kube-apiserver kube-controller-manager kubecfg kube-scheduler /opt/kubernetes/bin [root@kubernetes amd64]# scp kube-proxy kubelet root@192.168.230.4:/opt/kubernetes/bin [root@kubernetes amd64]# scp kube-proxy kubelet root@192.168.230.5:/opt/kubernetes/bin
為了簡單我們只部署一臺etcd伺服器,如果需要部署etcd的叢集,請參考官方文件,在本文中將其跟Kubernetes APIServer部署同一臺機器上,而且將etcd放置在/opt/kubernetes/bin下,etcdctl跟ectd同一目錄。
[root@kubernetes kubernetes]# cd /tmp/kubernetes/etcd-v0.4.6-linux-amd64 [root@kubernetes etcd-v0.4.6-linux-amd64]# cp etcd etcdctl /opt/kubernetes/bin
需注意的是kubernetes和minion上/opt/kubernetes/bin目錄下的檔案都必須是可執行的。到目前,我們準備工作已經差不多,現在開始給apiserver,controller-manager,scheduler,etcd配置unit檔案。首先我們用如下指令碼etcd.sh配置etcd的unit檔案,
#!/bin/sh ETCD_PEER_ADDR=192.168.230.3:7001 ETCD_ADDR=192.168.230.3:4001 ETCD_DATA_DIR=/var/lib/etcd ETCD_NAME=kubernetes ! test -d $ETCD_DATA_DIR && mkdir -p $ETCD_DATA_DIR cat <<EOF >/usr/lib/systemd/system/etcd.service [Unit] Description=Etcd Server [Service] ExecStart=/opt/kubernetes/bin/etcd \\ -peer-addr=$ETCD_PEER_ADDR \\ -addr=$ETCD_ADDR \\ -data-dir=$ETCD_DATA_DIR \\ -name=$ETCD_NAME \\ -bind-addr=0.0.0.0 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable etcd systemctl start etcd
對剩下的apiserver,controller-manager,scheduler的unit檔案配置的指令碼,可以在github 上GetStartingKubernetes找到,在此就不一一列舉。執行相應的指令碼後,在APIServer上etcd, apiserver, controller-manager, scheduler服務就能正常執行。
4.3 安裝Kubernetes Kubelet及Proxy
根據Kubernetes的設計架構,需要在minion上部署docker, kubelet, kube-proxy,在4.2節部署APIServer時,我們已經將kubelet和kube-proxy已經分發到兩minion上,所以只需配置docker,kubelet,proxy的unit檔案,然後啟動服務就即可,具體配置見GetStartingKubernetes。
5. 演示Kubernetes管理容器
為了方便,我們使用Kubernetes提供的例子Guestbook來演示Kubernetes管理跨機器執行的容器,下面我們根據Guestbook的步驟建立容器及服務。在下面的過程中如果是第一次操作,可能會有一定的等待時間,狀態處於pending,這是因為第一次下載images需要一段時間。
5.1 建立redis-master Pod和redis-master服務
[root@kubernetes ~]# cd /tmp/kubernetes/kubernetes/examples/guestbook [root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 -c redis-master.json create pods [root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 -c redis-master-service.json create services
完成上面的操作後,我們可以看到如下redis-master Pod被排程到192.168.230.4。
[root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 list pods Name Image(s) Host Labels Status ---------- ---------- ---------- ---------- ---------- redis-master dockerfile/redis 192.168.230.4/ name=redis-master Running
但除了發現redis-master的服務之外,還有兩個Kubernetes系統預設的服務kubernetes-ro和kubernetes。而且我們可以看到每個服務都有一個服務IP及相應的埠,對於服務IP,是一個虛擬地址,根據apiserver的portal_net選項設定的CIDR表示的IP地址段來選取,在我們的叢集中設定為10.10.10.0/24。為此每新建立一個服務,apiserver都會在這個地址段中隨機選擇一個IP作為該服務的IP地址,而埠是事先確定的。對redis-master服務,其服務地址為10.10.10.206,埠為6379。
[root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 list services Name Labels Selector IP Port ---------- ---------- ---------- ---------- ---------- kubernetes-ro component=apiserver,provider=kubernetes 10.10.10.207 80 redis-master name=redis-master name=redis-master 10.10.10.206 6379 kubernetes component=apiserver,provider=kubernetes 10.10.10.161 443
5.2 建立redis-slave Pod和redis-slave服務
[root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 -c redis-slave-controller.json create replicationControllers [root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 -c redis-slave-service.json create services
然後通過list命令可知新建的redis-slave Pod根據排程演算法排程到兩臺minion上,服務IP為10.10.10.92,埠為6379
[root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 list pods Name Image(s) Host Labels Status ---------- ---------- ---------- ---------- ---------- redis-master dockerfile/redis 192.168.230.4/ name=redis-master Running 8c0ddbda-728c-11e4-8233-000c297db206 brendanburns/redis-slave 192.168.230.5/ name=redisslave,uses=redis-master Running 8c0e1430-728c-11e4-8233-000c297db206 brendanburns/redis-slave 192.168.230.4/ name=redisslave,uses=redis-master Running [root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 list services Name Labels Selector IP Port ---------- ---------- ---------- ---------- ---------- redisslave name=redisslave name=redisslave 10.10.10.92 6379 kubernetes component=apiserver,provider=kubernetes 10.10.10.161 443 kubernetes-ro component=apiserver,provider=kubernetes 10.10.10.207 80 redis-master name=redis-master name=redis-master 10.10.10.206 6379
5.3 建立Frontend Pod和Frontend服務
在建立之前修改frontend-controller.json的Replicas數量為2,這是因為我們的叢集中只有2臺minion,如果按照frontend-controller.json的Replicas預設值3,那會導致有2個Pod會排程到同一臺minion上,產生埠衝突,有一個Pod會一直處於pending狀態,不能被排程。
[root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 -c frontend-controller.json create replicationControllers [root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 -c frontend-service.json create services
通過檢視可知Frontend Pod也被排程到兩臺minion,服務IP為10.10.10.220,埠是80。
[root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 list pods Name Image(s) Host Labels Status ---------- ---------- ---------- ---------- ---------- redis-master dockerfile/redis 192.168.230.4/ name=redis-master Running 8c0ddbda-728c-11e4-8233-000c297db206 brendanburns/redis-slave 192.168.230.5/ name=redisslave,uses=redis-master Running 8c0e1430-728c-11e4-8233-000c297db206 brendanburns/redis-slave 192.168.230.4/ name=redisslave,uses=redis-master Running a880b119-7295-11e4-8233-000c297db206 brendanburns/php-redis 192.168.230.4/ name=frontend,uses=redisslave,redis-master Running a881674d-7295-11e4-8233-000c297db206 brendanburns/php-redis 192.168.230.5/ name=frontend,uses=redisslave,redis-master Running [root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 list services Name Labels Selector IP Port ---------- ---------- ---------- ---------- ---------- kubernetes-ro component=apiserver,provider=kubernetes 10.10.10.207 80 redis-master name=redis-master name=redis-master 10.10.10.206 6379 redisslave name=redisslave name=redisslave 10.10.10.92 6379 frontend name=frontend name=frontend 10.10.10.220 80 kubernetes component=apiserver,provider=kubernetes 10.10.10.161 443
除此之外,你可以刪除Pod、Service及更新ReplicationController的Replicas數量等操作,如刪除Frontend服務:
[root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 delete services/frontend Status ---------- Success
還可以更新ReplicationController的Replicas的數量,下面是更新Replicas之前ReplicationController的資訊。
[root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 list replicationControllers Name Image(s) Selector Replicas ---------- ---------- ---------- ---------- redisSlaveController brendanburns/redis-slave name=redisslave 2 frontendController brendanburns/php-redis name=frontend 2
現在我們想把frontendController的Replicas更新為1,則這行如下命令,然後再通過上面的命令檢視frontendController資訊,發現Replicas已變為1。
[root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 resize frontendController 1 [root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 list replicationControllers Name Image(s) Selector Replicas ---------- ---------- ---------- ---------- redisSlaveController brendanburns/redis-slave name=redisslave 2 frontendController brendanburns/php-redis name=frontend 1
5.4 演示跨機器服務通訊
完成上面的操作後,我們來看當前Kubernetes叢集中執行著的Pod資訊。
[root@kubernetes guestbook]# kubecfg -h http://192.168.230.3:8080 list pods Name Image(s) Host Labels Status ---------- ---------- ---------- ---------- ---------- a881674d-7295-11e4-8233-000c297db206 brendanburns/php-redis 192.168.230.5/ name=frontend,uses=redisslave,redis-master Running redis-master dockerfile/redis 192.168.230.4/ name=redis-master Running 8c0ddbda-728c-11e4-8233-000c297db206 brendanburns/redis-slave 192.168.230.5/ name=redisslave,uses=redis-master Running 8c0e1430-728c-11e4-8233-000c297db206 brendanburns/redis-slave 192.168.230.4/ name=redisslave,uses=redis-master Running
通過上面的結果可知當前提供前端服務的PHP和提供資料儲存的後端服務Redis master的Pod分別執行在192.168.230.5和192.168.230.4上,即容器執行在不同主機上,還有Redis slave也執行在兩臺不同的主機上,它會從Redis master同步前端寫入Redis master的資料。下面我們從兩方面驗證Kubernetes能提供跨機器間容器的通訊:
- 在瀏覽器開啟http://${IPAddress}:8000,IPAddress為PHP容器執行的minion的IP地址,其暴漏的埠為8000,這裡IP_Address為192.168.230.5。開啟瀏覽器會顯示如下資訊:你可以輸入資訊並提交,如”Hello Kubernetes”、”Container”,然後Submit按鈕下方會顯示你輸入的資訊。
由於前端PHP容器和後端Redis master容器分別在兩臺minion上,因此PHP在訪問Redis master服務時一定得跨機器通訊,可見Kubernetes的實現方式避免了用link只能在同一主機上實現容器間通訊的缺陷,對於Kubernetes跨機器通訊的實現方法,以後我會詳細介紹。
- 從上面的結果,可得知已經實現了跨機器的通訊,現在我們從後端資料層驗證不同機器容器間的通訊。根據上面的輸出結果發現Redis slave和Redis master分別排程到兩臺不同的minion上,在192.168.230.4主機上執行docker exec -ti c41711cc8971 /bin/sh,c41711cc8971是Redis master的容器ID,進入容器後通過redis-cli命令檢視從瀏覽器輸入的資訊如下:如果我們在192.168.230.5上執行的Redis slave容器裡查到跟Redis master容器裡相同的資訊,那說明Redis master和Redis slave之間的資料同步正常工作,下面是從192.168.230.5上執行的Redis slave容器查詢到的資訊:
由此可見Redis master和Redis slave之間資料同步正常,OVS GRE隧道技術使得跨機器間容器正常通訊。
6. 結論
本文主要介紹如何在本地環境部署Kubernetes叢集和演示如何通過Kubernetes管理叢集中執行的容器,並通過OVS管理叢集不同minion的Pod之間的網路通訊。接下來會對Kubernetes各個元件原始碼進行詳細分析,闡述Kubernetes的工作原理。
相關文章
- Docker實踐(6)—CentOS7上部署KubernetesDockerCentOS
- Centos7安裝Nginx實戰CentOSNginx
- KubeSphere 最佳實戰:Kubernetes 部署叢集模式 Nacos 實戰指南模式
- Kubernetes實戰:高可用叢集的搭建和部署
- centos 7安裝部署elasticsearch 7.5.1CentOSElasticsearch
- CentOS7上部署httpsCentOSHTTP
- CentOS7離線部署JDKCentOSJDK
- centos7部署djangoCentOSDjango
- centos 7 部署k8sCentOSK8S
- Kubernetes(K8s)部署 SpringCloud 服務實戰K8SSpringGCCloud
- Centos 7.x 線上安裝 KubernetesCentOS
- CentOS 7 Docker安裝部署Go WebCentOSDockerGoWeb
- CentOS7 docker安裝部署教程CentOSDocker
- Docker 實戰之 CentOS7 系統環境配置DockerCentOS
- 實戰!教你如何使用KVM製作centos7映象!CentOS
- FastDFS概念、原理及CentOS7下安裝實戰ASTCentOS
- Centos8.3、docker部署springboot專案實戰記錄CentOSDockerSpring Boot
- CentOS7部署geoserver和postgisCentOSServer
- CentOS7 輕鬆部署 Laravel 應用CentOSLaravel
- asp.net core 2.1 部署 centos7ASP.NETCentOS
- Centos7系統部署django專案CentOSDjango
- Centos7安裝安裝部署dockerCentOSDocker
- Centos7部署Redis叢集CentOSRedis
- CentOS7 Hbase-1.3.1 分散式部署CentOS分散式
- CentOS7 .NetCore+Nginx 部署CentOSNetCoreNginx
- CentOS7部署Docker(聯網)CentOSDocker
- centos7下zookeeper叢集安裝部署CentOS
- eBPF in kubernetes 實戰eBPF
- kubernetes 實戰[1]
- Centos7部署nmon監控工具CentOS
- Centos 7下Nginx+uWsgi部署Flask應用CentOSNginxFlask
- centOS 7-Hadoop3.3.0完全分散式部署CentOSHadoop分散式
- centos7後臺服務部署jar包CentOSJAR
- k8s_centos7 安裝部署corednsK8SCentOSDNS
- CentOS7下Elasticsearch叢集部署記錄CentOSElasticsearch
- CentOS7 Tomcat JSP 安裝部署CentOSTomcatJS
- CentOS7 Hadoop-2.7.4 分散式部署CentOSHadoop分散式
- CentOS7 Apache+Mono Web站點部署CentOSApacheMonoWeb