寫在前面的話
經過上一節,我們順利將 K8S 集群搭建了起來,在其中我也簡單的談了一下關於 K8S 的網絡。那么這一節我們主要談談如何來簡單的使用 K8S 的命令。當然這些命令有很多,我們只是通過一個小例子來操作講解。是不全面的。
但是其實更多的目的是為了介紹一種方法。在后期的應用中,我們也會和 docker 一樣,慢慢的摒棄掉這種純手敲命令的形式,而且換成更為直觀的資源清單(yaml 文件)的形式。
而且本章節我們會好好談談在 K8S 中非常重要的幾個概念中的一部分,主要包括:Pod 和 Service 部分。
至於控制器 Controller 這些內容,我們會在更后邊的時候詳講。
關於 Pod
我們一直都在說,Pod 是 K8S 能夠調度的最小單元。那啥是 Pod?
Pod 其實是一個容器集,由 1 個甚至多個容器組成,它們的關系屬於緊密到不宜分割。一個 Pod 內的所有容器都運行在同一個節點上。
我們可以做個比喻,把一個學校比作 K8S,我們每個人就像一個容器,那么一個班就是一個 Pod,同專業多個班一起組成 Service,學校一般調度都是調度的專業,當然他也可以調度某個班。但我們可以假設他不會有事沒事專門去調度某個學生。
同一組的 Pod 共享 networks / uts / storage / volumes,通過 IPC 機制進行通訊。跨 Pod 的容器需要外部網絡插件實現通信,每一個 Pod 有一個屬於自己的 IP,此時容器就不再有自己的 IP 了。
對於 K8S 而言,最初和最終的目的都是為了運行 Pod,至於其他一些組件,其目的還是為了服務運行 Pod。
Pod 可以分為兩類:自主式 Pod 和控制器管理的 Pod。
此時我們再回頭來看用戶訪問 K8S 的服務就可以這樣理解:
用戶訪問的其實是某個提供服務的 Pod,請求先是到達宿主機(Node IP)的對應端口,然后將其轉發給指定的 Service(Cluster IP),然后通過 kube-proxy 的 ipvs 規則再度將其轉發到指定的 Pod(Pod IP)。當然到達 Pod 仍然會有相應的規則訪問到 Pod 內的指定容器。
在我們使用集群的時候,還是建議在 K8S 集群外部再度加一層作為 Load Balance,同時輔以 Keepalive 實現高可用。
至於如果我們想隔離 Pod,只需要采用不同的名稱空間(Namespace)就行。
關於 Service
當請求到達宿主機(Node IP)的時候,請求是無法直接到達 Pod 的,而且還可能是多個 Pod 的情況。
所以我們需要在這一個或者多個 Pod 前面再給它加一層,用來提供一個固定的訪問端點(Cluster IP)。
通過標簽選擇器(Label selector)讓 Pod 和這個訪問端點(Service)進行綁定,就能實現 Service 網絡和 Pod 網絡的通信。
但我們最終目的還是實現宿主機 Node 網絡和 Service 網絡通信,這就需要 K8S 一個附件(DNS)來實現。具體細節就不多講,我們大致知道這些原理就行。
你可能會有學習 docker 容器時一樣的疑問,后端 Pod 說不定就重構了,IP 變了,豈不意味這我們需要關注 Service 的配置?
這是完全沒有必要的,我們提到了 Service 網絡到 Pod 網絡是通過 Label selector 標簽選擇器綁定,這意味着,只要你標簽不變,無論怎么更新,Service 上面的解析地址永遠是對的。
同理,我們在 Node 上訪問 Service 網絡也不需要有這些擔心,因為這里也不是直接通過 IP 訪問,而且通過特定的名稱。
最后需要記住,每組 Pod 應用都該擁有自己單獨的 Service 進行調度。
關於 Controller
我們這里只是簡單的先讓大家知道有控制器這個東西,至於更加詳細的關於各種控制器的功能,會在之后特定的資源清單的時候詳解。
那么,啥是控制器(Controller)?
我們之前在第一節講 Master 組成的時候說過,Master 由 Controller-manager / Scheduler / APIServer 組成,那時候說過,Controller-manager 是集群中進行統一資源管理的東西。那么 Controller 的作用就是管理 Pod 的運行規則。
在 K8S 中常見的 Controller 有以下幾種:
1. ReplicationController
2. RelicaSet
3. Deployment(我們當前用的最多的,也是默認的)
4. StatefulSet
5. DeamonSet
6. Job,Cronjob
K8S 命令提示不全
這里單獨提一下,當我們手敲 K8S 命令的時候,很多時候需要去 --help 看參數命令,這顯然不方便,我們這里提供一個能夠讓我們 tab 鍵提示命令的配置。注意,第一配置后需要登出再次登錄讓環境生效。
yum install -y bash-completion source /usr/share/bash-completion/bash_completion source <(kubectl completion bash) echo "source <(kubectl completion bash)" >> ~/.bashrc
K8S 命令
我們可以通過 kubectl -h 查看到 K8S 支持的命令,這里我做個簡單的整理說明:
參數 | 說明 |
---|---|
create | 從文件或者輸入創建 |
run | 在集群中運行一個指定的鏡像(幾乎沒用了) |
expose | 創建 Service |
set | 給對象設置一個指定的特征 |
explain | 查看資源的文檔(重要,幫助查參數) |
get | 獲取資源信息(用的最多) |
edit | 直接編輯資源運行狀態 |
delete | 通過文件或者其他刪除資源 |
rollout | 主要用於版本升級和版本回滾(重要) |
scale | 直接更新資源的副本數量 |
autoscale | 自動調整資源的副本數量 |
certificate | 修改 certificate 資源 |
cluster-info | 顯示集群信息 |
top | 顯示系統資源使用情況 |
cordon | 標記 node 為 unschedulable |
uncordon | 標記 node 為 schedulable |
taint | 更新 node 的 taints |
describe | 顯示指定資源的詳情(實用) |
logs | 輸出容器在 pod 中的日志(重要,用於排錯) |
attach | 進入到一個運行中的 container |
exec | 在一個 container 中執行一個命令 |
port-forward | 端口轉發 |
proxy | 運行一個 proxy 到 Kubernetes API server |
cp | 復制 |
auth | Inspect authorization |
diff | Diff live version against would-be applied version |
apply | 通過文件名或輸入對資源進行配置(非常重要) |
patch | 更新資源的 field(s) |
replace | 通過文件或者輸入換一個資源 |
wait | Experimental: Wait for a specific condition on one or many resources |
convert | 在不同的 API versions 轉換配置文件 |
kustomize | Build a kustomization target from a directory or a remote url |
label | 更新在這個資源上的標簽 |
annotate | 更新一個資源的注解 |
completion | Output shell completion code for the specified shell (bash or zsh) |
api-resources | Print the supported API resources on the server |
api-versions | Print the supported API versions on the server, in the form of "group/version" |
config | 修改 kubeconfig 文件 |
plugin | Provides utilities for interacting with plugins |
version | 輸出 client 和 server 的版本信息 |
有些沒有翻譯或者標記的,要么用的比較少,要么現階段意義不大。
示例:增刪查改一個 Nginx Pod
我們通過一個示例,看看整個過程中我們用到了那些命令。
【1】創建一個 Nginx Pod:
kubectl run nginx-demo --image=nginx:1.14-alpine --port=80 --replicas=1
結果如圖:
這里簡單的對命令進行一個說明:
我們通過 run 運行一個 deployment 控制器取名為 nginx-demo,並通過 --image 指定了鏡像版本,--port 說明了服務端口,只是說明,並不能暴露端口,--replicas 指明了副本運行數量。
在命令執行過程中會有一個提示,不用在意,我們只需要看到下面 created,表明這個服務是創建成功的。
【2】查看 deployment 信息:
# 獲取存在的 deployment kubectl get deployment # 查看指定 deployment 信息 kubectl get deployment nginx-demo -o wide # 查看指定 deployment 詳細的信息 kubectl describe deployment nginx-demo
結果如圖:
這里有兩個點需要知道,一是 -o wide,這個是顯示更多信息,除此之外還有 -w,這個是動態顯示,有點像 linux 的 top 命令。
另外一個就是 describe 命令的作用,該命令能夠幫我排查啟動過程中的錯誤,非常實用。
【3】查看 Pod 信息同理:
# 查看有哪些 pod kubectl get pods # 查看指定 pod kubectl get pods nginx-demo-549b77b6c5-5nwhz -o wide # 查看指定 pod 詳細信息 kubectl describe pods nginx-demo-549b77b6c5-5nwhz
結果如圖:
我們能夠看到該 Pod 運行的節點與分配到的 IP 地址。
【4】集群內訪問測試 Pod:
curl 10.1.2.2
結果如圖:
可以看到集群內部是可以直接訪問到 Pod 網段並訪問到 Pod 的服務的。但是集群外部不行。
【5】讓外部網絡也能訪問到 Nginx:
之前我們說過,想讓外部訪問,我們必須把在 Pod 外面再套一層 Service,讓 Service 和宿主機之間做 DNS 解析。
所以我們來創建一個 Service:
kubectl expose deployment nginx-demo --name=nginx-svc --port=80 --target-port=80 --type=NodePort
這個命令可以看成,我們將名為 nginx-demo 的 deployment 的 80 端口暴露出去,並給這個 service 取名為 nginx-svc。
至於 type 的意義,后面我們會詳細的講解。
【6】查看創建的 Service:
# 查看有哪些 Service kubectl get svc # 查看指定 Service kubectl get svc nginx-svc -o wide
我們這里把 services 簡寫成 svc,方便使用。這種事情在 K8S 中很常見。結果如圖:
可以看到,我們的服務被映射成為 32118 端口,這個端口是一個大於 30000 的隨機端口。
可以使用集群中任意節點 IP + 32118 端口訪問到 Nginx:
【7】查看日志:
kubectl logs nginx-demo-549b77b6c5-5nwhz
結果如圖:
【8】集群管理(擴容和縮減)
# 擴容成3個 kubectl scale deployment nginx-demo --replicas=3 # 查看 kubectl get deployment nginx-demo -o wide
結果如圖:
同理,如果要減少節點數,只需要將 replicas 減小就行。
【9】版本升級與回滾:
首先來看下版本升級,其實際就是將鏡像的版本做變更:
kubectl set image deployment nginx-demo nginx-demo=nginx:1.15-alpine --record
查看更新后結果:
kubectl describe deployment nginx-demo
結果如圖:
此時,我們可以查看我們升級過的版本:
kubectl rollout history deployment nginx-demo
結果如圖:
因為有了這個東西,我們回滾版本就有了兩種選擇,一是回滾上個版本,一是回滾指定版本:
# 回滾上個版本 kubectl rollout undo deployment nginx-demo # 回滾指定版本 kubectl rollout undo deployment nginx-demo --to-revision=2
--to-reversion 指定的數字就是通過 history 看到的編號。
【10】最后就是刪除操作:
刪除 Pod:
kubectl delete pod nginx-demo-76844fcc4d-49hf2
結果如圖:
可以看到刪除成功了,但是並沒有意義,因為 K8S 會再給我啟動一個新的,這就是 K8S 的自愈能力。
刪除 deployment:
kubectl delete deployment nginx-demo
結果如圖:
得到的結論是,deployment 刪除,pod 也就跟着刪除。
刪除 Service:
kubectl delete svc nginx-svc
結果如圖:
小結
我們這里提到的其實就是一小部分命令和參數,后續還會有很多,這得再之后用到的時候才方便詳細講解,后面也不會再以命令為主。
但這並不意味着這些基礎的命令我們可以不知道,這些屬於我們學習 K8S 的基礎。