為何使用K8S
由于大型單體應(yīng)用轉(zhuǎn)變成微服務(wù)架構(gòu)阳藻,因?yàn)槲⒎?wù)能獨(dú)立開(kāi)發(fā)、部署谈撒、升級(jí)腥泥、伸縮,更加靈活啃匿。但由于微服務(wù)組件越來(lái)越多蛔外,使得配置、管理并保持系統(tǒng)的正常運(yùn)行越來(lái)越困難溯乒,所以K8S提供了對(duì)它們的自動(dòng)調(diào)度夹厌、配置、監(jiān)管和故障處理的功能裆悄。開(kāi)發(fā)者可以自主部署應(yīng)用矛纹,選擇回退版本、多版本部署光稼、控制部署的頻率或南。
Pod
Pod是容器組。一個(gè)Pod下的所有容器共享相同的主機(jī)名和網(wǎng)絡(luò)钟哥,能夠在內(nèi)部通過(guò)回環(huán)地址與其他容器互相通信迎献,所以注意同個(gè)pod下的容器不能綁定相同的端口號(hào),否則會(huì)導(dǎo)致端口沖突腻贰。不同Pod下的容器永遠(yuǎn)不會(huì)遇到端口沖突吁恍。同一Pod中的各容器是共享一些資源的,其實(shí)就是namespace是打通了共享的資源。Pod有如下?tīng)顟B(tài):
- pending(掛起) 例如沒(méi)有適合的節(jié)點(diǎn)運(yùn)行pod
- running (運(yùn)行)
- failed (失敿酵摺)
- succeeded(成功)
- unknown
同一pod下的共享資源有如下:
PID命名空間:Pod中的不同應(yīng)用程序可以看到其他應(yīng)用程序的進(jìn)程ID伴奥;
網(wǎng)絡(luò)命名空間:Pod中的多個(gè)容器能夠訪問(wèn)同一個(gè)IP和端口范圍;
IPC命名空間:Pod中的多個(gè)容器能夠使用SystemV IPC或POSIX消息隊(duì)列進(jìn)行通信翼闽;
UTS命名空間:Pod中的多個(gè)容器共享一個(gè)主機(jī)名拾徙;
Volumes(共享存儲(chǔ)卷):Pod中的各個(gè)容器可以訪問(wèn)在Pod級(jí)別定義的Volumes
Node
Node是Pod真正運(yùn)行的主機(jī),可以是物理機(jī)感局,也可以是虛擬機(jī)尼啡。為了管理Pod,每個(gè)Node節(jié)點(diǎn)上至少要運(yùn)行container runtime(例如docker)询微、kubelet和kube-proxy服務(wù)崖瞭,Node有如下?tīng)顟B(tài):
- Ready:節(jié)點(diǎn)正常
- NotReady: 節(jié)點(diǎn)斷開(kāi)
Namespace
相同Namespace的服務(wù)可以相互通訊,反之相互隔離撑毛。此Namespace與pod中的命名空間是不一樣的书聚,k8s 中的Namespace指的是提供了一個(gè)作用域,而Pod中命名空間是linux內(nèi)核提供的命名空間(主機(jī)名藻雌、網(wǎng)絡(luò)雌续、文件系統(tǒng)、進(jìn)程等各個(gè)維度)胯杭。所謂的作用域驯杜,例如通過(guò)建立Service訪問(wèn)Pod時(shí),如果Service的Namespace不正確歉摧,那么就無(wú)法正常關(guān)聯(lián)到Pod艇肴。k8s中的集群默認(rèn)會(huì)有一個(gè)叫default的Namespace。主要是2個(gè):
- default:App默認(rèn)被創(chuàng)建于此叁温。
- kube-system:kubernetes系統(tǒng)組件使用再悼。
這個(gè)默認(rèn)(default)的Namespace并沒(méi)什么特別,但你不能刪除它膝但。這很適合剛剛開(kāi)始使用k8s和一些小的服務(wù)的系統(tǒng)冲九。但不建議應(yīng)用于大型生產(chǎn)系統(tǒng)。因?yàn)樵趶?fù)雜系統(tǒng)中跟束,團(tuán)隊(duì)會(huì)非常容易意外地或者無(wú)意識(shí)地重寫或者中斷其他服務(wù)Service莺奸。相反,請(qǐng)創(chuàng)建多個(gè)命名空間來(lái)把你的服務(wù)Service分割成更容易管理的塊冀宴。
kubectl get ns
查看命名空間列表
--通過(guò)文件創(chuàng)建--
$ cat my-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: new-namespace
$ kubectl create -f ./my-namespace.yaml
--或者使用apply--更新
--刪除灭贷,注意會(huì)刪除該空間下所有資源--
$ kubectl delete namespaces new-namespace
注意刪除一個(gè)Namespace后,會(huì)把此Namespace下的所有資源刪除略贮,還有可能會(huì)出現(xiàn)Terminating狀態(tài)的namespace甚疟,這里不細(xì)講
kubectl delete ns 名稱 --force --grace-period=0
Deployment
ReplicationController現(xiàn)在已經(jīng)過(guò)時(shí)了仗岖,建議使用Deployment 配合ReplicaSet。ReplicationController的主要功能是保證Pod的數(shù)量览妖、健康轧拄,彈性收縮等。但是Deployment除了有這些功能之外讽膏,還增加了回滾功能(當(dāng)升級(jí) pod 鏡像或者相關(guān)參數(shù)的時(shí)候檩电,如果有錯(cuò)誤,可以回滾到上一個(gè)穩(wěn)定版本)府树,版本記錄(每一次對(duì) Deployment 的操作都能保存下來(lái))俐末。暫停和啟動(dòng)(升級(jí)的時(shí)候,能隨時(shí)暫停和啟動(dòng))挺尾。雖然ReplicaSets可以獨(dú)立使用鹅搪,但是它主要被作為協(xié)調(diào)作用的Pod創(chuàng)建站绪,刪除和更新的機(jī)制遭铺。在k8s中,有一個(gè)叫做kube-controller-manager的組件恢准。這個(gè)組件魂挂,是一系列控制器的集合,我們創(chuàng)建的Controller按定義的配置進(jìn)行容器編排
apiVersion: apps/v1
kind: Deployment
metadata:
name: busybox-deployment-v1
spec:
replicas: 3
selector:
matchLabels:
app: busybox-v1
template:
metadata:
labels:
app: busybox-v1
spec:
containers:
- name: busybox-host
image: busybox:1.31.1
command: ["sleep"]
args: ["1000"]
Labels
spec.selector.matchLables
與spec.template.metadata.lables
的區(qū)別馁筐。正確的Deployment書寫方式涂召,是要讓這2個(gè)值完全匹配,這樣才不會(huì)報(bào)錯(cuò)敏沉。matchLables是必須的果正。例如app:nginx表示用app=nginx的標(biāo)簽來(lái)創(chuàng)建pod實(shí)例
StatefulSet
Deployment不足以覆蓋所有的應(yīng)用編排問(wèn)題,因?yàn)樵谒磥?lái)盟迟,一個(gè)應(yīng)用的所有Pod是完全一樣的秋泳,所以它們之間就沒(méi)有順序,也無(wú)所謂運(yùn)行在哪臺(tái)宿主機(jī)上攒菠。需要時(shí)迫皱,Deployment就通過(guò)Pod模板創(chuàng)建新的Pod,不需要時(shí)辖众,就"殺掉"任意一個(gè)Pod卓起。但是在實(shí)際場(chǎng)景中,并不是所有應(yīng)用都滿足這樣的要求凹炸。比如:主從關(guān)系戏阅、主備關(guān)系、還有就是數(shù)據(jù)存儲(chǔ)類的多個(gè)實(shí)例通常會(huì)在本地磁盤上保存一份數(shù)據(jù)啤它,而這些實(shí)例一旦被殺掉奕筐,即使重建出來(lái)私杜,實(shí)例與數(shù)據(jù)之間的對(duì)應(yīng)關(guān)系也已經(jīng)丟失,從而導(dǎo)致應(yīng)用失敗救欧。這種實(shí)例之間有不對(duì)等關(guān)系衰粹,或者有依賴關(guān)系的應(yīng)用,被稱為“有狀態(tài)應(yīng)用(Stateful Application)”笆怠,為了支持這種铝耻,Kubernetes在Deployment基礎(chǔ)上擴(kuò)展出了StatefulSet。這塊功能可以用其他方式解決蹬刷,對(duì)于公用的基礎(chǔ)依賴瓢捉,應(yīng)該單獨(dú)抽離出來(lái),配合Deployment也可以落地實(shí)現(xiàn)
Service
通過(guò)Service來(lái)訪問(wèn)Pod办成,外部的Service可以通過(guò)其他的Service的ClusterIP來(lái)訪問(wèn)Pod泡态。每個(gè)PodIP由網(wǎng)絡(luò)插件動(dòng)態(tài)隨機(jī)分配(Pod重啟后IP地址會(huì)改變)。ClusterIP只在集群內(nèi)部可訪問(wèn)
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector: #service通過(guò)selector和pod建立關(guān)聯(lián)
app: nginx
不設(shè)置type迂卢,這種Service查看詳情會(huì)發(fā)現(xiàn)
spec:clusterIP=None某弦,這種被稱為headless serivces,通過(guò)這種方式selector選擇的pod可以直接從service的endpoints暴露的ip端口進(jìn)行連接而克,而不是通過(guò)service的CLUSTER-IP間接訪問(wèn)pod
kubectl describe svc myservice
查看詳情
ClusterIP類型
當(dāng)使用ClusterIP類型靶壮,可以使用以下方式訪問(wèn),這種方式的負(fù)載均衡已經(jīng)確定员萍,可以使用Istio組件來(lái)替換默認(rèn)的負(fù)載均衡
$ kubectl proxy --port=8080
curl http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/
NodePort類型
當(dāng)使用NodePort類型腾降,在所有Node上開(kāi)放一個(gè)特定端口,任何發(fā)送到該端口的流量都被轉(zhuǎn)發(fā)到對(duì)應(yīng)服務(wù)碎绎。NodePort 服務(wù)主要有兩點(diǎn)區(qū)別于普通的“ClusterIP”服務(wù)螃壤。第一,它的類型是“NodePort”筋帖。有一個(gè)額外的端口奸晴,稱為 nodePort,它指定節(jié)點(diǎn)上開(kāi)放的端口值 幕随。如果你不指定這個(gè)端口蚁滋,系統(tǒng)將選擇一個(gè)隨機(jī)端口。大多數(shù)時(shí)候我們應(yīng)該讓 Kubernetes 來(lái)選擇端口赘淮,讓開(kāi)發(fā)者自己來(lái)選擇可用端口比較麻煩辕录。這種方式每個(gè)端口只能是一種服務(wù),而且端口范圍只能是 30000-32767梢卸。不建議在生產(chǎn)環(huán)境上用這種方式暴露服務(wù)走诞。如果你運(yùn)行的服務(wù)不要求一直可用,或者對(duì)成本比較敏感蛤高,你可以使用這種方法蚣旱。這樣的應(yīng)用的最佳例子是 demo 應(yīng)用碑幅,或者某些臨時(shí)應(yīng)用
apiVersion: v1
kind: Service
metadata:
name: my-nodeport-service
selector:
app: my-app
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30036
protocol: TCP
LoadBalancer類型
使用LoadBalancer類型。這個(gè)方式的最大缺點(diǎn)是每一個(gè)用 LoadBalancer 暴露的服務(wù)都會(huì)有它自己的實(shí)際的IP地址塞绿,用在公有云上沟涨,不允考慮
Endpoints
Endpoints把k8s外部應(yīng)用或服務(wù)的address和port發(fā)布到k8s,作為內(nèi)部Service的依賴异吻。如果endpoints和service是同一個(gè)名字裹赴,那么就自動(dòng)關(guān)聯(lián)
apiVersion: v1
kind: Endpoints
metadata:
name: mysql-process
namespace: mysql
subsets:
# k8s外部服務(wù)的地址和端口
- addresses:
- ip: 10.0.0.82
ports:
- port: 3306
內(nèi)部虛擬IP,只有k8s內(nèi)部的控制器可連接
apiVersion: v1
kind: Service
metadata:
name: mysql-process
namespace: mysql
spec:
ports:
- port: 3306
Ingress
Ingress是對(duì)service的更高層次的抽象诀浪,service是工作在tcp/ip層棋返,基于ip和port的,那么ingress是針對(duì)http 7層路由機(jī)制雷猪,將客戶端的請(qǐng)求直接轉(zhuǎn)發(fā)到service對(duì)應(yīng)的后端pod服務(wù)上
使用Ingress類型睛竣。最強(qiáng)大的,最靈活求摇。Nginx ingress是k8s所推薦的默認(rèn)的ingress射沟。缺點(diǎn):當(dāng)路由配置非常大的時(shí)候,Nginx reload 會(huì)耗時(shí)非常久月帝,可以達(dá)到幾秒甚至十幾秒躏惋,Nginx ingress的插件能力和可擴(kuò)展性比較差
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
backend:
serviceName: other
servicePort: 8080
rules:
- host: foo.mydomain.com
http:
paths:
- backend:
serviceName: foo
servicePort: 8080
- host: mydomain.com
http:
paths:
- path: /bar/*
backend:
serviceName: bar
servicePort: 8080
發(fā)布文件配置說(shuō)明
appVersion
1.extensions/v1beta1是用于kubernetes版本在1.6之前
2.apps/v1beta1是用于1.6-1.9版本之間
3.apps/v1是1.9版本以后使用
目前使用的是1.16.3版本可以正常使用apps/v1,使用下面命令查看是否支持某項(xiàng)聲明
kubectl api-versions