目的
隨著部署組件的增多和數(shù)據(jù)中心的增長(zhǎng), 配置以及管理并保持系統(tǒng)的正常運(yùn)行變得復(fù)雜與困難.
在想要獲得足夠高的資源利用率并降低硬件成本情況下, 把組件部署在什么地方變得越來(lái)越難以決策.
自動(dòng)化調(diào)度, 配置, 監(jiān)管以及故障處理, 正式 k8s 解決的痛點(diǎn)
帶來(lái)的便捷
為應(yīng)用程序提供一致的環(huán)境, 便于今早發(fā)現(xiàn)問(wèn)題
提供更加便捷的持續(xù)交付能力
<img src="https://cdn.jsdelivr.net/gh/chaimcode/FigureBed@master/uPic/6A7B416B-5B08-4CB7-A727-EE83303AC36F.png" alt="k8s架構(gòu)" style="zoom:67%;" />
組件介紹
控制面板用于控制集群工作, 其中包含的組件可以部署在多個(gè)節(jié)點(diǎn)上以保證高可用性
kubernetes API 服務(wù)器 | 控制面板中各個(gè)組件之間通信的橋梁 |
---|---|
schedule | 應(yīng)用調(diào)度器 |
controller manager | 執(zhí)行集群級(jí)別功能, eg: 復(fù)制組件, 持續(xù)跟蹤工作節(jié)點(diǎn), 處理失敗節(jié)點(diǎn)等 |
etcd | 分布式數(shù)據(jù)存儲(chǔ), 持久化存儲(chǔ)集群配置 |
工作節(jié)點(diǎn)是運(yùn)行容器化應(yīng)用的機(jī)器
容器運(yùn)行時(shí) | docker 等其他的容器類(lèi)型 |
---|---|
kubelet | 與 api 服務(wù)器通信, 并管理它所在節(jié)點(diǎn)的容器 |
kube-proxy | 負(fù)責(zé)組件之間的負(fù)載均衡網(wǎng)絡(luò)流量 |
容器生命周期示例
docker build -t kubia . |
---|
docker images | grep kubia |
docker run --name kubia-container -p 8080:8080 -d kubia |
curl localhost:8080 |
docker inspect kubia-container |
docker exec -ti kubia-container bash |
docker stop kubia-container |
docker rm kubia-container |
docker tag kubia mingch94/kubia |
docker push mingch94/kubia |
環(huán)境準(zhǔn)備
yum install bash-completion | 安裝 bash-completion |
---|---|
source <(kubectl completion bash) | 生效 kubectl 的自動(dòng)補(bǔ)全 |
alias k=kubectl | 設(shè)置 kubectl 的別稱(chēng) |
source <(kubectl completion bash | sed s/kubectl/k/g) | 調(diào)整別稱(chēng) k 的自動(dòng)補(bǔ)全 |
alias kcd='k config set-context $(k config current-context) --namespace' | 設(shè)置切換名稱(chēng)空間別稱(chēng) |
集群操作
kubectl cluster-info | 查看集群狀態(tài) |
---|---|
kubectl get nodes | 列出集群節(jié)點(diǎn) |
kubectl describe node docker-desktop | 查看集群節(jié)點(diǎn)更多信息 |
k run kubia --image=mingch94/kubia --port=8080 | 部署應(yīng)用 |
k get po | 列出 pod |
k describe po kubia | 查看 pod 更多詳細(xì)信息 |
k apply -f https://k8s.io/examples/controllers/replication.yaml | 創(chuàng)建 rc |
k get rc | 查看 rc 資源 |
k expose po kubia --type=LoadBalancer --name kubia-http | 創(chuàng)建服務(wù), 對(duì)外暴露 pod |
k get svc | 查看服務(wù)對(duì)象 |
curl localhost:8080 | 訪問(wèn)服務(wù) |
k scale rc kubia —replicas=3 | 水平擴(kuò)展 pod 到 3 個(gè) |
get pods -o wide | 展示更多列 |
k get po kubia -o yaml | 檢查現(xiàn)有 pod 的 yaml 描述 |
k explain po | 解析 pod 定義 |
k explain pod.spec | 查看 spec 屬性 |
k create -f kubia-manual.yaml | 從 yml 創(chuàng)建 pod |
kubectl logs kubia-manual -c kubia | 查看 pod 中容器 kubia 的日志 |
k port-forward kubia-manual 8888:8080 | 將本地 8888 流量轉(zhuǎn)發(fā)到 pod 的 8080 端口 |
k get po --show-labels | 查看 pod 以及所有的 label |
k get po -L creation_method,env | 標(biāo)簽單獨(dú)展示到對(duì)應(yīng)列 |
k label po kubia-manual creation_method=manual | 創(chuàng)建標(biāo)簽 |
k label po kubia-manual-v2 env=debug --overwrite | 修改標(biāo)簽 |
k get po -l creation_method=manual | 指定標(biāo)簽值查詢(xún) pod |
k get po -l env | 指定標(biāo)簽名查詢(xún) pod |
k get po -l '!env' | 指定不包含 env 標(biāo)簽名查詢(xún) pod, 支持 !, in, notin |
k label node docker-desktop gpu=true | 給 node 添加指定的標(biāo)簽 |
k annotate pod kubia-manual mycompany.com/someannotation="foo bar" | 創(chuàng)建注解 |
k get ns | 查看集群中所有的命名空間 |
k get po -n kube-system | 查看指定命名空間的 pod |
k create ns custom-namespace | 創(chuàng)建命名空間 |
k config get-contexts | 查看當(dāng)前上下文以及對(duì)應(yīng)使用的名稱(chēng)空間 |
k delete pod kubia-gpu | 根據(jù)名稱(chēng)刪除 pod |
k delete po -l creation_method=manual | 根據(jù)標(biāo)簽刪除 pod |
k delete ns custom-namespace | 刪除名稱(chēng)空間以及其下邊所有的 pod |
k delete po --all | 刪除所有的 pod |
k delete all --all | 刪除當(dāng)前名稱(chēng)空間下所有資源 |
k logs kubia-liveness --previous | 獲取前一個(gè)容器日志 |
k edit rc kubia | 編輯 rc |
k delete rc kubia --cascade=false | 僅刪除 rc, 保留 pod 正常運(yùn)行 |
k get rs | 查看 rc |
k get ds | 查看 ds |
k get jobs | 查看 jobs |
k exec kubia-p5mz5 -- curl -s http://10.96.72.201 | pod 中執(zhí)行命令, - - 代表 kubectl 命令的結(jié)束, 如待執(zhí)行命令無(wú) - 參數(shù)可去掉 |
k exec -it kubia-72v4k -- bash | 交互式進(jìn)入 pod 中執(zhí)行命令 |
k get endpoints | 查看 endpoints 資源 |
k get nodes -o json | json 方式展示 node 信息 |
k get po --all-namespaces | 顯示所有 ns 下的的 pod |
k get ingresses | 查看 ingress 服務(wù) |
k run dnsutils --image=tutum/dnsutils | 使用帶 dns 的 pod |
k proxy | 通過(guò) kube-proxy 與 api 服務(wù)器進(jìn)行交互, 訪問(wèn)根路徑可以查看當(dāng)前支持的 api |
k create -f kubia-deployment-v1.yaml --record | 創(chuàng)建 deployment 資源, --record 表示記錄版本號(hào) |
k patch deployment kubia -p '{"spec": {"minReadySeconds": 10}}' | 設(shè)置 pod 創(chuàng)建完成后至少 10s 后才可用 |
k set image deployment kubia nodejs=luksa/kubia:v2 | 修改鏡像為 luksa/kubia:v2 , 鏡像名稱(chēng)為 nodejs |
k rollout status deployment kubia | 查看升級(jí)過(guò)程 |
k rollout undo deployment kubia | 回滾到上一個(gè)版本 |
k rollout undo deployment kubia --to-revision=1 | 回滾到指定版本 |
k rollout pause deployment kubia | 暫停滾動(dòng)升級(jí) |
k rollout resume deployment kubia | 取消滾動(dòng)升級(jí), 回滾到上一個(gè)版本 |
k apply -f kubia-deployment-v3-with-readinesscheck.yaml | 通過(guò)一個(gè)完整的 yml 定義來(lái)修改對(duì)象 |
當(dāng)一個(gè) pod 包含多個(gè)容器時(shí)候, 這些容器總是會(huì)運(yùn)行在同一個(gè)節(jié)點(diǎn). 也就是一個(gè) pod 絕不會(huì)跨越多個(gè)工作節(jié)點(diǎn)
由于不能講多個(gè)進(jìn)程聚集在一個(gè)單獨(dú)的容器中, 因此需要一種更高級(jí)的結(jié)構(gòu)將容器綁定在一起, 也就是 pod. 可以把 pod 理解為現(xiàn)實(shí)世界中的主機(jī)
同一個(gè) pod 中的容器共享相同的 ip 和端口, 因此可以通過(guò) localhost 與同一個(gè) pod 中的其他容器通信
pod 定義的幾個(gè)主要部分
API 版本以及 YAML 描述的資源類(lèi)型 | apiVersion, kind |
---|---|
metadata 包括 名稱(chēng), 命名空間, 標(biāo)簽以及其他容器信息 | name, namespace, labels |
spec 包括 pod 內(nèi)容的實(shí)際說(shuō)明(容器, 卷和其他數(shù)據(jù)) | containers, volumes |
status 包含當(dāng)前運(yùn)行的 pod 的信息(所處條件, 容器描述和狀態(tài), 內(nèi)部 IP 等) | conditions, containerStatuses, phase, hostIP |
# Kubernets API 版本為 v1
apiVersion: v1
# 資源類(lèi)型為 pod
kind: Pod
metadata:
# 資源名稱(chēng)為 kubia-maual
name: kubia-manual
spec:
containers:
# 指定鏡像
- image: luksa/kubia
# 容器名稱(chēng)
name: kubia
ports:
# 容器監(jiān)聽(tīng)的端口為 8080
- containerPort: 8080
protocol: TCP
名稱(chēng)空間不對(duì)正在運(yùn)行的對(duì)象做任何隔離, 同時(shí)名稱(chēng)空間之間的網(wǎng)絡(luò)是否隔離取決于 k8s 采取的網(wǎng)絡(luò)解決方案
如果需要部署的應(yīng)用自動(dòng)保持運(yùn)行且保持健康, 無(wú)任何手動(dòng)干預(yù), 則不能直接創(chuàng)建 pod, 而是創(chuàng)建 rc 或 deployment 這樣的資源來(lái)管理 pod.
直接創(chuàng)建的 pod 只會(huì)被 k8s 監(jiān)控失敗重啟(節(jié)點(diǎn)上的 Kubelet 操作的), 但是整個(gè)節(jié)點(diǎn)失敗, 無(wú)法被新節(jié)點(diǎn)替換
探測(cè)容器機(jī)制
HTTP GET 探針 | 對(duì)容器的 IP 地址執(zhí)行 HTTP GET 請(qǐng)求. 響應(yīng)狀態(tài)碼為 2xx 或 3xx 時(shí)候則認(rèn)為探測(cè)成功 |
---|---|
TCP 套接字探針 | 嘗試與容器指定端口建立 TCP 連接. 連接成功建立則探測(cè)成功. 否則容器重啟 |
Exec 探針 | 在容器內(nèi)執(zhí)行任意命令, 并檢車(chē)命令的退出狀態(tài)碼. 狀態(tài)碼為 0 則探測(cè)成功 |
<img src="https://cdn.jsdelivr.net/gh/chaimcode/FigureBed@master/uPic/B0FB8A20-553A-4485-8E60-148CC71491C6.png" alt="標(biāo)簽匹配過(guò)程" style="zoom:67%;" />
ReplicationController 三要素
label selector | 標(biāo)簽選擇器, 用于確定 rc 作用域中有哪些 pod |
---|---|
replica count | 副本個(gè)數(shù), 指定應(yīng)運(yùn)行的 pod 數(shù)量, 會(huì)影響現(xiàn)有的 pod |
pod template | pod 模板, 用于創(chuàng)建新的 pod 副本 |
rc 版本
apiVersion: v1
# rc 類(lèi)型
kind: ReplicationController
metadata:
# rc 名稱(chēng)
name: kubia
spec:
# 副本數(shù)量
replicas: 3
# 標(biāo)簽選擇器
selector:
app: kubia
# 創(chuàng)建新 pod 時(shí)候的模板
template:
metadata:
labels:
# 模板中的標(biāo)簽必須與標(biāo)簽選擇器中的一致, 避免無(wú)休止的創(chuàng)建 pod
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia
ports:
- containerPort: 8080
rs 版本
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: kubia
spec:
replicas: 3
selector:
matchExpressions:
- key: app
operator: In
values:
- kubia
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia
ds 版本
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ssd-monitor
spec:
selector:
matchLabels:
app: ssd-monitor
template:
metadata:
labels:
app: ssd-monitor
spec:
nodeSelector:
disk: ssd
containers:
- name: main
image: luksa/ssd-monitor
batch-job 版本
apiVersion: batch/v1
kind: Job
metadata:
name: batch-job
spec:
template:
metadata:
labels:
app: batch-job
spec:
restartPolicy: OnFailure
containers:
- name: main
image: luksa/batch-job
service 版本
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
# 會(huì)話親和性, 同一個(gè)clientIP 的流量會(huì)被發(fā)送到同一個(gè) pod
sessionAffinity: ClientIP
ports:
# 服務(wù)可用端口
- port: 80
# 服務(wù)將連接轉(zhuǎn)發(fā)到的容器端口
targetPort: 8080
selector:
# 具有 app=kubia 標(biāo)簽的 pod 都屬于該服務(wù)
app: kubia
內(nèi)部集群測(cè)試服務(wù)
創(chuàng)建 pod | 請(qǐng)求發(fā)送到服務(wù)的集群 ip 并記錄響應(yīng), 可通過(guò) pod 的日志查看響應(yīng) |
---|---|
ssh 到任意節(jié)點(diǎn) | 在遠(yuǎn)程 node 上執(zhí)行 curl |
kubectl exec | 在一個(gè)已經(jīng)存在的 pod 中執(zhí)行 cul 命令 |
將服務(wù)暴露給外部客戶(hù)端
NodePort | 集群節(jié)點(diǎn)在節(jié)點(diǎn)上打開(kāi)一個(gè)端口, 并將該端口上的流量重定向到基礎(chǔ)服務(wù) |
---|---|
LoadBalance | NodePort 類(lèi)型的一種擴(kuò)展, 使得服務(wù)可以通過(guò)專(zhuān)用的負(fù)載均衡器訪問(wèn) |
Ingress | 通過(guò)一個(gè) IP 地址公開(kāi)多個(gè)服務(wù), 運(yùn)行在 7 層網(wǎng)絡(luò) |
<img src="https://cdn.jsdelivr.net/gh/chaimcode/FigureBed@master/uPic/323FEC99-B6B0-4E3C-B2FA-5F388C874471.png" alt="service 示例" style="zoom:67%;" />
<img src="https://cdn.jsdelivr.net/gh/chaimcode/FigureBed@master/uPic/5B8D9494-DAAB-45F4-BC5D-9BE4DE43D85F.png" alt="負(fù)載均衡器示例" style="zoom:67%;" />
<img src="https://cdn.jsdelivr.net/gh/chaimcode/FigureBed@master/uPic/2F90060C-70C2-4FCA-BCDA-6E0159BE28E3.png" alt="ingress 示例" style="zoom:67%;" />
幾種常見(jiàn)的卷類(lèi)型
更多詳細(xì)見(jiàn) https://kubernetes.io/docs/concepts/storage/volumes/
emptyDir | 存儲(chǔ)臨時(shí)數(shù)據(jù)的簡(jiǎn)單空目錄 |
---|---|
hostPath | 將目錄從工作節(jié)點(diǎn)的文件系統(tǒng)掛載到 pod 中, 指向節(jié)點(diǎn)文件系統(tǒng)上特定的文件或目錄. 持久性的卷, 但是 pod 一旦調(diào)度到其它節(jié)點(diǎn)就會(huì)有問(wèn)題 |
gitRepo | 檢出 git 倉(cāng)庫(kù)的內(nèi)容來(lái)初始化券 |
nfs | 掛載到 pod 的 nfs 共享卷 |
gcePersistentDIsk | google 的高效能存儲(chǔ)磁盤(pán)卷 |
awsElasticBlockStore | aws 的服務(wù)彈性塊存儲(chǔ)卷 |
azureDisk | Microsoft Zaure 磁盤(pán)卷 |
configMap, secret, downwardAPI | 將 k8s 部分資源和集群信息公開(kāi)給 pod 的特殊卷 |
persistentVolumeClaim | 預(yù)置或動(dòng)態(tài)配置的持久性存儲(chǔ)類(lèi)型 |
emptyDir 卷使用
apiVersion: v1
kind: Pod
metadata:
name: fortune
spec:
containers:
- image: luksa/fortune
name: html-generator
volumeMounts:
# 名為 html 的卷掛載在容器 /var/htdocs, 可讀可寫(xiě)
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
# 名為 html 的卷掛載在容器 /usr/share/nginx/html, 只讀
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
# 名為 html 的卷, 掛載在上面兩個(gè)容器中
- name: html
emptyDir: {}
gitRepo 卷使用
apiVersion: v1
kind: Pod
metadata:
name: gitrepo-volume-pod
spec:
containers:
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
gitRepo:
repository: https://github.com/chaimcode/kubia-website-example.git
revision: master
directory: .
api 服務(wù)使用
k proxy
curl http://localhost:8001
{
"paths": [
"/api",
"/api/v1",
"/apis",
"/apis/",
"/apis/admissionregistration.k8s.io",
"/apis/admissionregistration.k8s.io/v1",
"/apis/admissionregistration.k8s.io/v1beta1",
"/apis/apiextensions.k8s.io",
"/apis/apiextensions.k8s.io/v1",
"/apis/apiextensions.k8s.io/v1beta1",
"/apis/apiregistration.k8s.io",
"/apis/apiregistration.k8s.io/v1",
"/apis/apiregistration.k8s.io/v1beta1",
"/apis/apps",
"/apis/apps/v1",
"/apis/authentication.k8s.io",
"/apis/authentication.k8s.io/v1",
"/apis/authentication.k8s.io/v1beta1",
"/apis/authorization.k8s.io",
"/apis/authorization.k8s.io/v1",
"/apis/authorization.k8s.io/v1beta1",
"/apis/autoscaling",
"/apis/autoscaling/v1",
"/apis/autoscaling/v2beta1",
"/apis/autoscaling/v2beta2",
"/apis/batch",
"/apis/batch/v1",
"/apis/batch/v1beta1",
"/apis/certificates.k8s.io",
"/apis/certificates.k8s.io/v1beta1",
"/apis/compose.docker.com",
"/apis/compose.docker.com/v1alpha3",
"/apis/compose.docker.com/v1beta1",
"/apis/compose.docker.com/v1beta2",
"/apis/coordination.k8s.io",
"/apis/coordination.k8s.io/v1",
"/apis/coordination.k8s.io/v1beta1",
"/apis/events.k8s.io",
"/apis/events.k8s.io/v1beta1",
"/apis/extensions",
"/apis/extensions/v1beta1",
"/apis/networking.k8s.io",
"/apis/networking.k8s.io/v1",
"/apis/networking.k8s.io/v1beta1",
"/apis/node.k8s.io",
"/apis/node.k8s.io/v1beta1",
"/apis/policy",
"/apis/policy/v1beta1",
"/apis/rbac.authorization.k8s.io",
"/apis/rbac.authorization.k8s.io/v1",
"/apis/rbac.authorization.k8s.io/v1beta1",
"/apis/scheduling.k8s.io",
"/apis/scheduling.k8s.io/v1",
"/apis/scheduling.k8s.io/v1beta1",
"/apis/storage.k8s.io",
"/apis/storage.k8s.io/v1",
"/apis/storage.k8s.io/v1beta1",
"/healthz",
"/healthz/autoregister-completion",
"/healthz/etcd",
"/healthz/log",
"/healthz/ping",
"/healthz/poststarthook/apiservice-openapi-controller",
"/healthz/poststarthook/apiservice-registration-controller",
"/healthz/poststarthook/apiservice-status-available-controller",
"/healthz/poststarthook/bootstrap-controller",
"/healthz/poststarthook/ca-registration",
"/healthz/poststarthook/crd-informer-synced",
"/healthz/poststarthook/generic-apiserver-start-informers",
"/healthz/poststarthook/kube-apiserver-autoregistration",
"/healthz/poststarthook/rbac/bootstrap-roles",
"/healthz/poststarthook/scheduling/bootstrap-system-priority-classes",
"/healthz/poststarthook/start-apiextensions-controllers",
"/healthz/poststarthook/start-apiextensions-informers",
"/healthz/poststarthook/start-kube-aggregator-informers",
"/healthz/poststarthook/start-kube-apiserver-admission-initializer",
"/livez",
"/livez/autoregister-completion",
"/livez/etcd",
"/livez/log",
"/livez/ping",
"/livez/poststarthook/apiservice-openapi-controller",
"/livez/poststarthook/apiservice-registration-controller",
"/livez/poststarthook/apiservice-status-available-controller",
"/livez/poststarthook/bootstrap-controller",
"/livez/poststarthook/ca-registration",
"/livez/poststarthook/crd-informer-synced",
"/livez/poststarthook/generic-apiserver-start-informers",
"/livez/poststarthook/kube-apiserver-autoregistration",
"/livez/poststarthook/rbac/bootstrap-roles",
"/livez/poststarthook/scheduling/bootstrap-system-priority-classes",
"/livez/poststarthook/start-apiextensions-controllers",
"/livez/poststarthook/start-apiextensions-informers",
"/livez/poststarthook/start-kube-aggregator-informers",
"/livez/poststarthook/start-kube-apiserver-admission-initializer",
"/logs",
"/metrics",
"/openapi/v2",
"/readyz",
"/readyz/autoregister-completion",
"/readyz/etcd",
"/readyz/log",
"/readyz/ping",
"/readyz/poststarthook/apiservice-openapi-controller",
"/readyz/poststarthook/apiservice-registration-controller",
"/readyz/poststarthook/apiservice-status-available-controller",
"/readyz/poststarthook/bootstrap-controller",
"/readyz/poststarthook/ca-registration",
"/readyz/poststarthook/crd-informer-synced",
"/readyz/poststarthook/generic-apiserver-start-informers",
"/readyz/poststarthook/kube-apiserver-autoregistration",
"/readyz/poststarthook/rbac/bootstrap-roles",
"/readyz/poststarthook/scheduling/bootstrap-system-priority-classes",
"/readyz/poststarthook/start-apiextensions-controllers",
"/readyz/poststarthook/start-apiextensions-informers",
"/readyz/poststarthook/start-kube-aggregator-informers",
"/readyz/poststarthook/start-kube-apiserver-admission-initializer",
"/readyz/shutdown",
"/version"
]
}
deployment 版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubia
spec:
replicas: 3
selector:
matchExpressions:
- key: app
operator: In
values:
- kubia
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: luksa/kubia:v1
name: nodejs
deployment 需注意的屬性
minReadySeconds | pod 最少可用等待時(shí)間, 即使就緒探針?lè)祷爻晒? 也需要等改時(shí)間 |
---|---|
revisionHistoryLimit | 限制歷史版本數(shù)量 |
maxSurge | 滾動(dòng)升級(jí)時(shí)候, 期望的副本數(shù), 默認(rèn) 25%, 則如果副本數(shù)為 4, 則滾動(dòng)期間不會(huì)超過(guò) 5 個(gè) pod 實(shí)例 |
maxUnavailable | 滾動(dòng)升級(jí)時(shí)候, 允許最多多少 pod 不可用狀態(tài). |