引言
最近做邊緣計算專案,因為沒有基礎,所以首先學習Kubernetes,感覺系統的中文入門資料比較少,只找到《Kubernetes權威指南》(龔正、吳治輝等著,下稱《指南》),照著第一章的demo教程撰寫,前前后后遇到不少問題,也是找了好多資料才解決,所以從頭寫一下如何配置一個單機版MySQL+Tomcat的demo,希望能給陷入同樣困境的同學一點幫助,
文章較長,如果你已經按照《指南》的demo走了一遍,但是遇到了問題,可以直接看最后的“坑點總結”中的解決方案能否解決你的問題,
知識準備和環境準備
前導知識
本著對零基礎的同學友好的態度,前排提示閱讀本文前你至少需要以下知識:
- 掌握虛擬機的使用,尤其是網路的配置
- Linux的使用,尤其是CentOS 7的systemctl功能
- 了解如何更換軟體安裝源(主要是yum和docker)
- 了解docker和容器的基本概念
- 大致了解yaml
- 可能的kexue上網方法(但一般可以通過更換軟體源代替)
也就是說,以上的知識本文不會詳細展開,如果其中有讀者從來沒有聽說過的概念,最好先學習一下,
實驗環境
筆者的實驗環境:
Win10 + VMWare14中安裝CentOS 7(帶GUI),橋接模式上網
之所以強調是CentOS 7(包括RHEL 7),是因為它的系統服務配置使用的是systemctl命令,這可能與其他CentOS版本或Linux發行版有所不同,當然,如果你對Linux的系統服務配置有經驗,可以不采用和筆者相同的版本,
另外,下面所有操作最好在root下進行,避免出現權限不足的問題,
Kubernetes安裝和配置
基本上按照《指南》中的環境準備如下:
關閉防火墻
終端輸入以下命令關閉防火墻:
systemctl disable firewalld #禁止防火墻開機啟動
systemctl stop firewalld #關閉防火墻服務
如果tab之后有后綴.service是一樣的,不帶后綴的是簡稱,
可以使用下面的命令查看防火墻是否已經關閉,如果是inactive表明已關閉:
systemctl status firewalld
當然,生產環境需要自己配置埠訪問控制,不能完全關閉防火墻,這里因為是較安全的內網,學習和測驗用,直接關閉比較方便,
安裝etcd和Kubernetes
yum install -y etcd kubernetes
kubernetes的每個組件有各自的組態檔,可以自定義,而該命令會執行默認配置的安裝,對kubernetes尚不了解時一鍵安裝非常方便,
如果安裝緩慢,可以嘗試更換國內的yum安裝源,或者代理上網(虛擬機可以共享物理機的代理埠,SSR和clash軟體都有允許局域網共享的功能),
修改組態檔
此處需要修改兩處組態檔,
- Docker組態檔
Docker組態檔為/etc/sysconfig/docker,將OPTIONS的內容設定為:
OPTIONS='--selinux-enabled=false --insecure-registry gcr.io'
可以注釋OPTIONS所在行,而非洗掉它,以留出容錯空間ω,
- Kubernetes apiserver組態檔
Kubernetes apiserver組態檔為/etc/kubernetes/apiserver,將--admission_control引數中的ServiceAccount洗掉(同樣地,可以注釋原行,復制一行來修改),也就是更改為:
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
也許你的--admission_control引數并不是在KUBE_ADMISSION_CONTROL變數下,但是在哪里其實是一樣的,只要之后的變數讀取都有錄入即可(不細講,筆者也尚未完全學習),這里只需要洗掉,
啟動kubernetes服務
按順序啟動以下服務:
systemctl start etcd
systemctl start docker
systemctl start kube-apiserver
systemctl start kube-controller-manager
systemctl start kube-scheduler
systemctl start kubelet
systemctl start kube-proxy
至于為什么要按順序,筆者認為是因為后面的服務對前面的有依賴,啟動順序不對可能會導致某些意外錯誤,
這里有一個坑點,就是kube-apiserver啟動時必須要開啟網路連接,否則會報錯:
Job for kube-apiserver.service failed because the control process exited with error code. See "systemctl status kube-apiserver.service" and "journalctl -xe" for details.
因為筆者系統是帶GUI的,直接在右上角設定網路連接即可,如果是純字符界面可能需要自己開啟網路服務,
另外,將start選項改為stop和restart分別是停止服務和重啟服務,改為enable表示加入開機啟動串列,
一鍵啟動腳本
因為是學習階段,出現各種錯誤老是需要開開關關,所以寫了一個一鍵啟動的腳本,
創建service-list.txt檔案,按順序寫上所有需要啟動的服務名稱:
etcd
docker
kube-apiserver
kube-controller-manager
kube-scheduler
kubelet
kube-proxy
創建腳本檔案k8s-service-start.sh:
#!/bin/bash
for SERVNAME in `cat service-list.txt`
do
systemctl status $SERVNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "Already Active : $SERVNAME"
else
systemctl start $SERVNAME
systemctl status $SERVNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "Start Success : $SERVNAME"
else
echo "! Start fail : $SERVNAME"
fi
fi
done
記得給腳本加上執行權限:
chmod +x k8s-service-start.sh
當然,如果已經使用systemctl enable加入了開機啟動就無需重復操作了,
Docker鏡像加速
一般從官方網站下載Docker鏡像都比較慢,所以設定一下國內源進行鏡像加速,
在/etc/docker/daemon.json 中寫入如下內容(如果檔案不存在請新建該檔案):
{"registry-mirrors":["你的鏡像加速地址"]}
我使用的是阿里云源,在阿里云賬號的“容器鏡像服務 - 鏡像中心 - 鏡像加速器”選單中可以找到你專屬的鏡像加速地址,
你也可以使用其他地址:
網易:https://hub-mirror.c.163.com/
七牛云:https://reg-mirror.qiniu.com
之后重啟docker服務:
systemctl daemon-reload
systemctl restart docker
啟動MySQL服務
以上都是安裝和配置,下面正式進入到kubernetes的使用了,
首先最好新建一個作業檔案夾,方便管理,
撰寫mysql-rc檔案
在作業檔案夾下新建RC定義檔案mysql-rc.yaml,內容如下:
apiVersion: v1
kind: ReplicationController
metadata:
name: mysql
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7 #若不加版本號5.7,可能會導致錯誤
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
這里yaml檔案中的kind屬性,用來表示資源物件的型別,比如這里就表示一個RC,(最外層的)spec一節表示RC的相關屬性定義,如replicas表示期望實體數量,template是創建POD實體的模板,注意template中的labels必須與前面的selector匹配,
原版書的spec.containers.image沒有寫版本號,默認拉取latest鏡像,這可能會導致一些不兼容的錯誤,筆者使用5.7版本沒有問題,
另外注意縮進要正確,
撰寫mysql-svc檔案
新建Service定義檔案mysql-svc.yaml,內容如下:
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
啟動Service和發布RC
檔案撰寫完畢后,就可以啟動Service和發布RC了,
- 創建Service:
kubectl create -f mysql-svc.yaml
# 正確輸出:service "mysql" created
此外對應地,可以用如下命令洗掉服務:
kubectl delete -f mysql-svc.yaml
- 查看Service是否創建成功:
kubectl get svc
# 正確輸出:
# NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# kubernetes 10.254.0.1 <none> 443/TCP 2d
# mysql 10.254.21.86 <none> 3306/TCP 17h
其中CLUSTER-IP是kubernetes為POD自動分配的集群內IP,與宿主機無關(且與宿主機網段不能重合),
- 發布RC:
kubectl create -f mysql-rc.yaml
# 正確輸出:replicationcontroller "mysql" created
- 查看RC狀態:
kubectl get rc
# 正確輸出,READY應為1:
# NAME DESIRED CURRENT READY AGE
# mysql 1 1 1 17h
查看POD狀態:
kubectl get pods
# 正確輸出,READY應為1,STATUS應為Running:
# NAME READY STATUS RESTARTS AGE
# mysql-8811b 1/1 Running 1 17h
如果STATUS為Pending或ContainerCreating,說明還在下載或創建容器,可以等待片刻,如果長時間處于此狀態,或者狀態變為CrashLoopBackOff或Error,說明出現了某些錯誤,可以檢查一下所有的服務是否已開啟,yaml檔案撰寫有無錯誤(拼寫、縮進、多余的空格等),
讀者可能注意到,之前是先撰寫rc檔案再撰寫svc檔案的,但此處是先創建Service再發布RC,實際上,《指南》中是先發布RC再創建Service的,但有博客說這樣啟動出現了一些問題(雖然不是這個例子),因此這里先創建Service再發布RC,
啟動MyWeb服務
上一節定義和啟動了MySQL服務,這里用同樣的步驟啟動Tomcat,也就是Web應用,
撰寫myweb-rc檔案
創建myweb-rc.yaml檔案,內容如下:
kind: ReplicationController
metadata:
name: myweb
spec:
replicas: 5
selector:
app: myweb
template:
metadata:
labels:
app: myweb
spec:
containers:
- name: myweb
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
# value: 'mysql'
value: 10.254.21.86 # 這里很坑,集群尚未啟動域名決議服務,需要直接填寫mysql服務的IP地址
- name: MYSQL_SERVICE_PORT
value: '3306'
這個檔案也很關鍵,按照《指南》里寫可能會出錯,坑點是MYSQL_SERVICE_HOST的值要直接寫mysql服務的IP地址,也就是之前使用kubectl get svc命令查看到的mysql的IP,
當然,真正應用時一定不會這么做,因為某個POD是有可能掛掉的,下次啟動時IP可能就會變,但是在剛剛入門時啥都不懂的情況下,這樣做是最快的,否則搞了半天看不到成功結果,是非常打擊學習興趣和信心的(筆者就是QwQ),
撰寫myweb-svc檔案
創建myweb-svc.yaml檔案,內容如下:
apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
selector:
app: myweb
啟動Service和發布RC
發布Service:
kubectl create -f myweb-svc.yaml
# 正確輸出:service "myweb" created
發布RC:
kubectl create -f myweb-rc.yaml
# 正確輸出:replicationcontroller "myweb" created
同樣地,可以用kubectl get命令來查看各種資源的狀態,
瀏覽器訪問網頁
終于到了激動人心的時刻,配置完畢,可以開始訪問網站了,
使用物理機的瀏覽器訪問:
http://虛擬機的IP:30001/demo/
如果成功,你會看到如下頁面:

點擊“Add...”可以增加記錄,
如果不能訪問,就用虛擬機自己的瀏覽器來訪問,如果虛擬機可以訪問,那么很可能是防火墻的問題,需要關閉后重啟kubernetes相關服務,再執行命令:
iptables -P FORWARD ACCEPT
如果還是不能解決,也許你要從頭開始檢查每個步驟,甚至可能遇到筆者未遇到的錯誤,假如下面一節的方法都不能解決你的問題,那么筆者也無能為力了orz!
Good luck!_
坑點總結
總結一下筆者踩到的坑,當然也不一定就是關鍵的錯誤,但下面的方案筆者都試過,
使用下面的命令查看pods的日志,可能有助于定位錯誤:
kubectl logs POD名
mysql無法鏈接
現象
可以訪問網頁,但瀏覽器顯示報錯:
Error:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
解決方案
有2種可能性:
- mysql版本不對,
- 無法進行域名決議
對于1,洗掉mysql的RC資源,將mysql-rc.yaml中的image引數改為mysql:5.7后重新發布,
對于2,將myweb-rc.yaml中MYSQL_SERVICE_HOST的value改為mysql服務的IP地址,也就是用kubectl get svc查看到的地址,重新發布RC,
物理機無法訪問網頁
現象
物理機無法訪問網頁,但虛擬機可以,
解決方案
- 查看防火墻狀態:
systemctl status firewalld
- 如果沒有關閉則手動關閉:
systemctl disable firewalld #禁止防火墻開機啟動
systemctl stop firewalld #關閉防火墻服務
-
重啟kubernetes相關服務
-
執行以下命令:
iptables -P FORWARD ACCEPT
無法啟動kube-apiserver
現象
啟動kube-apiserver報錯:
Job for kube-apiserver.service failed because the control process exited with error code. See "systemctl status kube-apiserver.service" and "journalctl -xe" for details.
解決方案
首先打開CentOS自己的網路連接,再啟動kube-apiserver,
RC狀態卡住
現象
RC的狀態卡在ContainerCreating/Pending,或變成CrashLoopBackOff/Error,
解決方案
檢查rc的yaml檔案有無錯誤,包括拼寫、縮進、多余的空格等,
如果檔案撰寫無誤,嘗試更換Docker國內鏡像源或kexue上網,
其他錯誤
現象
其他報錯,或者看不到報錯,但虛擬機和物理機都不能訪問,
解決方案
按照本文從頭檢查所有步驟,若仍然有錯可以嘗試:
- 洗掉所有RC和Service,先創建Service,再啟動RC
- 重啟所有kubernetes服務
- 重啟虛擬機
- 打開百度/谷歌/StackOverflow
參考資料:
k8s中部署 Tomcat+MySQL服務
在k8s中定義和啟動mysql和tomcat服務之后,瀏覽器無法訪問的問題
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/539365.html
標籤:其他
