Pod中的容器很可能因?yàn)楦鞣N原因發(fā)生故障而死掉罢浇。
而使用Deployment等Controller可以動(dòng)態(tài)創(chuàng)建和銷毀Pod來(lái)保證應(yīng)用整體的健壯性读第。
每個(gè)Pod都有自己的IP地址净蚤。當(dāng)Controller用新Pod替代發(fā)生故障的Pod時(shí),新Pod會(huì)分配到新的IP地址眯杏。如果直接通過(guò)Pod的ip訪問(wèn)服務(wù)开瞭,就會(huì)產(chǎn)生問(wèn)題懒震。
為了解決這個(gè)問(wèn)題罩息,Kubernetes提供了Service,并通過(guò)service訪問(wèn)pod中的服務(wù)挎狸。
創(chuàng)建Service
Service從邏輯上代表了一組Pod扣汪。Service有自己的IP断楷,而且這個(gè)IP是不變的锨匆。
客戶端只需要訪問(wèn)Service的IP,Kubernetes則負(fù)責(zé)建立和維護(hù)Service與Pod的映射關(guān)系冬筒。
看個(gè)例子恐锣,創(chuàng)建下面的這個(gè)Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd
spec:
replicas: 3
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: httpd
ports:
- containerPort: 80
啟動(dòng)了3個(gè)pod
pod分配了各自的IP,這些IP只能被集群內(nèi)的容器和節(jié)點(diǎn)訪問(wèn)
接下來(lái)創(chuàng)建Service舞痰,配置文件如下
apiVersion: v1
kind: Service
metadata:
name: httpd-svc
spec:
selector:
app: httpd
ports:
- protocol: TCP
port: 8080
targetPort: 80
①v1是Service的apiVersion土榴。
②指明當(dāng)前資源的類型為Service。
③Service的名字為httpd-svc响牛。
④selector使用標(biāo)簽和pod關(guān)聯(lián)玷禽。
⑤將Service的8080端口映射到Pod的80端口,使用TCP協(xié)議呀打。
執(zhí)行kubectl apply創(chuàng)建Service httpd-svc
[root@master ~]# kubectl apply -f httpd-svc.yml
service/httpd-svc created
[root@master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-svc ClusterIP 10.97.164.120 <none> 8080/TCP 40s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4h51m
httpd-svc分配到一個(gè)CLUSTER-IP 10.97.164.120矢赁。可以通過(guò)該IP訪問(wèn)后端的httpd Pod贬丛,根據(jù)前面的端口映射撩银,這里要使用8080端口
[root@master ~]# curl 10.97.164.120:8080
<html><body><h1>It works!</h1></body></html>
這和直接訪問(wèn)Pod IP:80是一樣的
除了我們創(chuàng)建的httpd-svc,還有一個(gè)Service kubernetes豺憔,Cluster內(nèi)部通過(guò)這個(gè)Service訪問(wèn)Kubernetes API Server额获。
通過(guò)describe查看service的詳細(xì)信息,從中可以看到Endpoints即為與之對(duì)應(yīng)的Pod
Cluster IP底層實(shí)現(xiàn)
CLUSTER-IP是如何映射到Pod IP的呢恭应?答案是iptables抄邀。
可以通過(guò)iptables-save命令打印出當(dāng)前節(jié)點(diǎn)的iptables規(guī)則
大概意思是經(jīng)過(guò)規(guī)則跳轉(zhuǎn),最終將請(qǐng)求轉(zhuǎn)發(fā)到后端的三個(gè)Pod昼榛。
結(jié)論:iptables將訪問(wèn)Service的流量轉(zhuǎn)發(fā)到后端Pod境肾,而且使用類似輪詢的負(fù)載均衡策略。
另外褒纲,需要補(bǔ)充一點(diǎn):Cluster的每一個(gè)節(jié)點(diǎn)都配置了相同的iptables規(guī)則准夷,這樣就確保了整個(gè)Cluster都能夠通過(guò)Service的Cluster IP訪問(wèn)Service
DNS訪問(wèn)Service
kubeadm部署時(shí)會(huì)默認(rèn)安裝coredns組件
coredns是一個(gè)DNS服務(wù)器。每當(dāng)有新的Service被創(chuàng)建莺掠,coredns會(huì)添加該Service的DNS記錄衫嵌。Cluster中的Pod可以通過(guò)<SERVICE_NAME>.<NAMESPACE_NAME>訪問(wèn)Service。
如下在一個(gè)臨時(shí)的busybox Pod中驗(yàn)證了DNS的有效性彻秆。
另外楔绞,由于這個(gè)Pod與httpd-svc同屬于default namespace结闸,因此可以省略default直接用httpd-svc訪問(wèn)Service
用nslookup查看httpd-svc的DNS信息
Server是DNS服務(wù)器
httpd-svc.default.svc.cluster.local是httpd-svc的完整域名
外網(wǎng)如何訪問(wèn)Service
Kubernetes提供了多種類型的Service,默認(rèn)是ClusterIP酒朵。
ClusterIP只能在Cluster內(nèi)部訪問(wèn)桦锄,如果要在外部訪問(wèn)service,這就要通過(guò)NodePort來(lái)實(shí)現(xiàn)蔫耽。
apiVersion: v1
kind: Service
metadata:
name: httpd-svc
spec:
type: NodePort
selector:
app: httpd
ports:
- protocol: TCP
port: 8080
targetPort: 80
添加type: NodePort结耀,重新創(chuàng)建httpd-svc
Kubernetes依然會(huì)為httpd-svc分配一個(gè)ClusterIP,8080是ClusterIP監(jiān)聽(tīng)的端口
除此之外匙铡,8080后的端口:31639图甜,則是節(jié)點(diǎn)監(jiān)聽(tīng)的端口,每個(gè)節(jié)點(diǎn)都會(huì)監(jiān)聽(tīng)此端口并將請(qǐng)求轉(zhuǎn)發(fā)給Service
在master節(jié)點(diǎn)上測(cè)試
集群外訪問(wèn)測(cè)試
這時(shí)鳖眼,集群外也可以訪問(wèn)服務(wù)了
NodePort默認(rèn)的是隨機(jī)選擇黑毅,可以用nodePort指定某個(gè)特定端口
現(xiàn)在配置文件中就有三個(gè)Port了:
(1)nodePort是節(jié)點(diǎn)上監(jiān)聽(tīng)的端口。
(2)port是ClusterIP上監(jiān)聽(tīng)的端口钦讳。
(3)targetPort是Pod監(jiān)聽(tīng)的端口矿瘦。
也可以通過(guò)expose
命令創(chuàng)建service
查看service
瀏覽器訪問(wèn)節(jié)點(diǎn)ip:30355