kubernetes(三)k8s中通信和Service
目錄
?
1.同一個(gè)Pod中的容器通信
2.集群內(nèi)Pod之間的通信
3 集群內(nèi)Service-Cluster IP
4.外部服務(wù)訪問集群中的Pod
4.1 Service-NodePort
4.2.Service-LoadBalance
4.3.Ingress
?
1.同一個(gè)Pod中的容器通信
Each Pod is assigned a unique IP address. Every container in a Pod shares the network namespace, including the IP address and network ports.?
K8S最小的操作單位是Pod,由官網(wǎng)的這段話可以看出,同一個(gè)pod中的容器是共享網(wǎng)絡(luò)ip地址和端口號(hào)的,通信顯然沒問題
在docker中,如果想在docker的網(wǎng)絡(luò)中使用docker 的container name來進(jìn)行通信,就需要通過connect命令將這些容器都加入到
同一個(gè)容器的網(wǎng)絡(luò)中
k8s中也是這樣做的,Pod里的這個(gè)容器被稱之為pause container。
每個(gè)Pod里除了我們?cè)趛aml文件里定義的容器等,都會(huì)有一個(gè)默認(rèn)的pause container
如下圖所示:
因?yàn)樵谝粋€(gè)網(wǎng)絡(luò)內(nèi),Pod里的容器可以通過ip和容器名進(jìn)行通信
k8s進(jìn)入容器命令:?
kubectl exec -it <podName> -c <containerName> -n <namespace> -- shell comand
2.集群內(nèi)Pod之間的通信
我們都知道Pod會(huì)有獨(dú)立的IP地址,這個(gè)IP地址是被Pod中所有的Container共享的
那么在多個(gè)Pod之間的通信能通過這個(gè)IP地址嗎?
從兩個(gè)角度考慮這個(gè)問題:一是集群中同一臺(tái)機(jī)器中的Pod,二是集群中不同機(jī)器中的Pod
準(zhǔn)備兩個(gè)pod:一個(gè)Nginx,一個(gè)Busybox(運(yùn)行一段小程序的應(yīng)用)
apiVersion: v1kind: Podmetadata:name: nginx-podlabels:app: nginxspec:containers:- name: nginx-containerimage: nginxports:- containerPort: 80 ---apiVersion: v1kind: Podmetadata:name: busyboxlabels:app: busyboxspec:containers:- name: busyboximage: busyboxcommand: ['sh', '-c', 'echo The app is running! && sleep 3600']運(yùn)行后查看兩個(gè)容器的運(yùn)行情況,這里剛好兩個(gè)pod都運(yùn)行在同一個(gè)Node上
發(fā)現(xiàn):nginx-pod的ip為192.168.80.202? ? ?busybox-pod的ip為192.168.80.203 這里的ip是由calico網(wǎng)絡(luò)插件幫助pod生成的
在任意一個(gè)Node,都可以通過Pod的ip進(jìn)行訪問(這里是Master節(jié)點(diǎn))
可以多試幾次,就有可能分別在不同的Node上 : 注意此時(shí)在兩個(gè)節(jié)點(diǎn)上都不能有對(duì)應(yīng)類型的Pod(nginx和busybox,否則k8s會(huì)默認(rèn)把Pod分配給不含有該類型Pod的節(jié)點(diǎn)
注意:這里在nginx容器內(nèi)ping busybox的ip無法成功,不是因?yàn)榫W(wǎng)絡(luò)原因,而是在容器內(nèi)不支持ping命令,根本原因是因?yàn)閚ginx的image鏡像里沒有對(duì)應(yīng)的layer層.(可以參考下這篇文章:docker學(xué)習(xí)筆記(二)創(chuàng)建自己的鏡像)
結(jié)論:centos上的任一集群nginx機(jī)器都能通過pod ip訪問對(duì)應(yīng)的pod
pods on a node can communicate with all pods on all nodes without NAT
pods in the host network of a node can communicate with all pods on all nodes without NAT
3 集群內(nèi)Service-Cluster IP
上述的Pod雖然實(shí)現(xiàn)了集群內(nèi)部互相通信,但是Pod是不穩(wěn)定的,比如通過Deployment管理Pod,隨時(shí)可能對(duì)Pod進(jìn)行擴(kuò)縮容,這時(shí)候Pod的IP地址是變化的。這就希望能夠有一個(gè)固定的IP,使得集群內(nèi)能夠訪問。
也就是前面在架構(gòu)描述的時(shí)候所提到的,能夠把相同或者具有關(guān)聯(lián)的Pod,打上Label,組成一個(gè)Service。由Service提供固定的IP訪問Pod集群。這樣一來,不管Pod怎么創(chuàng)建和銷毀,都可以通過不變的Service IP進(jìn)行訪問(這點(diǎn)其實(shí)跟docker swarm里的service很像)
An abstract way to expose an application running on a set of Pods as a network service.
Kubernetes gives Pods their own IP addresses and a single DNS name for a set of Pods, and can load-balance across them.
(1)創(chuàng)建一個(gè)有3個(gè)副本的whoami的yaml(Deployment)
apiVersion: apps/v1 kind: Deployment metadata:name: whoami-deploymentlabels:app: whoami spec:replicas: 3selector:matchLabels:app: whoamitemplate:metadata:labels:app: whoamispec:containers:- name: whoamiimage: jwilder/whoamiports:- containerPort: 8000(2)查看pod以及service
kubectl?get svc:可以發(fā)現(xiàn)目前并沒有關(guān)于whoami的service
在集群內(nèi)可以通過任一節(jié)點(diǎn)訪問whoami的Pod
(3)創(chuàng)建對(duì)應(yīng)的Service
kubectl expose deployment whoami-deployment??
發(fā)現(xiàn)有一個(gè)Cluster IP類型的service,名稱為whoami-deployment,IP地址為10.100.14.56
(4)通過對(duì)應(yīng)的Cluster IP訪問
這里的ClusterIP只能供集群內(nèi)部訪問
不難看出該service對(duì)三個(gè)pod實(shí)現(xiàn)了負(fù)載均衡
(5)具體查看一下whoami-deployment的詳情信息,發(fā)現(xiàn)有一個(gè)Endpoints連接了具體3個(gè)Pod
[root@m ~]# kubectl describe svc whoami-deployment
擴(kuò)容后,service里的Endpoints的Pod信息也會(huì)發(fā)生變化
[root@m ~]# kubectl scale deployment whoami-deployment --replicas=5 deployment.extensions/whoami-deployment scaled [root@m ~]# kubectl describe svc whoami-deployment Name: whoami-deployment Namespace: default Labels: app=whoami Annotations: <none> Selector: app=whoami Type: ClusterIP IP: 10.100.14.56 Port: <unset> 8000/TCP TargetPort: 8000/TCP Endpoints: 192.168.190.75:8000,192.168.190.76:8000,192.168.190.77:8000 + 2 more... Session Affinity: None Events: <none>(6)Service的創(chuàng)建除了前面的命令行kubectl expose的形式,還有yaml的方式
apiVersion: v1 kind: Service metadata:name: my-service spec:selector:app: MyAppports:- protocol: TCPport: 80targetPort: 9376type: Cluster4.外部服務(wù)訪問集群中的Pod
4.1 Service-NodePort
Service的一種類型,可以通過NodePort的方式讓外部服務(wù)訪問集群的Pod
因?yàn)橥獠渴悄軌蛟L問到集群機(jī)器的物理機(jī)器IP,所以NodePort就是在集群中每臺(tái)物理機(jī)器Node上暴露一個(gè)相同的IP,然后暴露一個(gè)端口將集群中的Pod映射到對(duì)應(yīng)的端口
(1)創(chuàng)建一個(gè)whoami的yaml
apiVersion: apps/v1 kind: Deployment metadata:name: whoami-deploymentlabels:app: whoami spec:replicas: 3selector:matchLabels:app: whoamitemplate:metadata:labels:app: whoamispec:containers:- name: whoamiimage: jwilder/whoamiports:- containerPort: 8000(2)創(chuàng)建NodePort類型的service,名稱為whoami-deployment
kubectl expose deployment whoami-deployment --type=NodePort
通過NodePort將容器內(nèi)部的8000端口映射到了宿主機(jī)的32717端口
注意:從請(qǐng)求的結(jié)果可以看出,雖然集群的每個(gè)Node都開放了一個(gè)端口供外部訪問service,但哪怕請(qǐng)求同一個(gè)ip:port,其內(nèi)部也是實(shí)現(xiàn)了負(fù)載均衡的
結(jié)論:NodePort雖然能夠?qū)崿F(xiàn)外部訪問Pod的需求,但其實(shí)不好,因?yàn)闀?huì)占用了各個(gè)物理主機(jī)上的端口(3個(gè)Node就會(huì)在3臺(tái)Node上各占用一個(gè)端口)
4.2.Service-LoadBalance
在Service上做端口映射 通常需要第三方云提供商支持,有約束性?
4.3.Ingress
https://kubernetes.io/docs/concepts/services-networking/ingress/
An API object that manages external access to the services in a cluster, typically HTTP.
Ingress can provide load balancing, SSL termination and name-based virtual hosting.
Ingress exposes HTTP and HTTPS routes from outside the cluster to?services?within the cluster. Traffic routing is controlled by rules defined on the Ingress resource.
簡單來說,Ingress就是幫助我們?cè)L問集群內(nèi)的服務(wù)
ingress包括:ingress controller和ingress resources
ingress controller:核心是一個(gè)deployment,實(shí)現(xiàn)方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,需要編寫的yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的類型可以是NodePort或者LoadBalancer。
ingress resources:這個(gè)就是一個(gè)類型為Ingress的k8s api對(duì)象了,這部分面向開發(fā)人員,用來配置一些映射規(guī)則
Ingress就相當(dāng)于一個(gè)負(fù)載均衡器,是k8s對(duì)反向代理的一個(gè)抽象。大概的工作原理類似于Nginx,可以理解成在 Ingress 里建立一個(gè)個(gè)映射規(guī)則 , Ingress Controller?通過監(jiān)聽 Ingress?這個(gè)api對(duì)象里的配置規(guī)則并轉(zhuǎn)化成 Nginx 的配置?, 然后對(duì)外部提供服務(wù)。
之所以需要分成ingress-controller和ingress resources,我覺得是由于網(wǎng)關(guān)部分的功能,大部分的組件都幫我們實(shí)現(xiàn)了,所以ingress直接提供controller接口,讓廠商去實(shí)現(xiàn)負(fù)載均衡等網(wǎng)關(guān)功能,使用方只需要關(guān)注映射配置了(相當(dāng)于把Nginx里的配置拿出來在yaml里進(jìn)行配置,不需要進(jìn)入容器內(nèi)去修改配置文件)
https://github.com/kubernetes/ingress-nginx
https://kubernetes.github.io/ingress-nginx/
(1)先定義我們要運(yùn)行的Service
apiVersion: apps/v1 kind: Deployment metadata:name: tomcat-deploymentlabels:app: tomcat spec:replicas: 1selector:matchLabels:app: tomcattemplate:metadata:labels:app: tomcatspec:containers:- name: tomcatimage: tomcatports:- containerPort: 8080 --- apiVersion: v1 kind: Service metadata:name: tomcat-service spec:ports:- port: 80 protocol: TCPtargetPort: 8080selector:app: tomcat(2)以Deployment方式創(chuàng)建Ingress Nginx Controller ?Pod
可以通過Service的NodePort或者HostPort方式讓外界訪問到,這里選擇HostPort,比如指定worker01運(yùn)行該P(yáng)od(給Node打標(biāo)簽,然后在指定標(biāo)簽的Node上運(yùn)行)
對(duì)應(yīng)的mandatory.yaml下載:https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
安裝指導(dǎo):https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md
# 確保nginx-controller運(yùn)行到w1節(jié)點(diǎn)上 kubectl label node w1 name=ingress # 使用HostPort方式運(yùn)行,需要增加配置 hostNetwork: truenginx-ingress-controller在w1啟動(dòng)成功
(3) 定義ingress規(guī)則
#ingress 訪問tomcat.chenpp.com的默認(rèn)路徑,轉(zhuǎn)發(fā)到tomcat-service的80端口 apiVersion: extensions/v1beta1 kind: Ingress metadata:name: nginx-ingress spec:rules:- host: tomcat.chenpp.comhttp:paths:- path: /backend:serviceName: tomcat-serviceservicePort: 80在本地的hosts(C:\Windows\System32\drivers\etc)文件下添加對(duì)應(yīng)的域名映射:
打開瀏覽器訪問成功
如果以后想要使用Ingress網(wǎng)絡(luò),其實(shí)只要定義ingress和service和pod即可,前提是要保證nginx ingress controller已經(jīng)配置好了。
在使用ingress的時(shí)候,如果發(fā)現(xiàn)當(dāng)pod和nginx-ingress-controller不在一個(gè)節(jié)點(diǎn)上無法訪問時(shí),可以設(shè)置下iptables,設(shè)置允許端口轉(zhuǎn)發(fā): iptables -P FORWARD? ACCEPT或者如下圖讓pod和ingress在一個(gè)節(jié)點(diǎn)上也可以
XXXXspec: containers: - name: tomcatimage: tomcatports: - containerPort: 8080nodeSelector:name: ingress?
總結(jié)
以上是生活随笔為你收集整理的kubernetes(三)k8s中通信和Service的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: kubernetes(二)k8s组件
- 下一篇: kubernetes(八)问题排查