kubernetes(三)k8s中通信和Service
目錄
?
1.同一個Pod中的容器通信
2.集群內Pod之間的通信
3 集群內Service-Cluster IP
4.外部服務訪問集群中的Pod
4.1 Service-NodePort
4.2.Service-LoadBalance
4.3.Ingress
?
1.同一個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,由官網的這段話可以看出,同一個pod中的容器是共享網絡ip地址和端口號的,通信顯然沒問題
在docker中,如果想在docker的網絡中使用docker 的container name來進行通信,就需要通過connect命令將這些容器都加入到
同一個容器的網絡中
k8s中也是這樣做的,Pod里的這個容器被稱之為pause container。
每個Pod里除了我們在yaml文件里定義的容器等,都會有一個默認的pause container
如下圖所示:
因為在一個網絡內,Pod里的容器可以通過ip和容器名進行通信
k8s進入容器命令:?
kubectl exec -it <podName> -c <containerName> -n <namespace> -- shell comand
2.集群內Pod之間的通信
我們都知道Pod會有獨立的IP地址,這個IP地址是被Pod中所有的Container共享的
那么在多個Pod之間的通信能通過這個IP地址嗎?
從兩個角度考慮這個問題:一是集群中同一臺機器中的Pod,二是集群中不同機器中的Pod
準備兩個pod:一個Nginx,一個Busybox(運行一段小程序的應用)
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']運行后查看兩個容器的運行情況,這里剛好兩個pod都運行在同一個Node上
發現:nginx-pod的ip為192.168.80.202? ? ?busybox-pod的ip為192.168.80.203 這里的ip是由calico網絡插件幫助pod生成的
在任意一個Node,都可以通過Pod的ip進行訪問(這里是Master節點)
可以多試幾次,就有可能分別在不同的Node上 : 注意此時在兩個節點上都不能有對應類型的Pod(nginx和busybox,否則k8s會默認把Pod分配給不含有該類型Pod的節點
注意:這里在nginx容器內ping busybox的ip無法成功,不是因為網絡原因,而是在容器內不支持ping命令,根本原因是因為nginx的image鏡像里沒有對應的layer層.(可以參考下這篇文章:docker學習筆記(二)創建自己的鏡像)
結論:centos上的任一集群nginx機器都能通過pod ip訪問對應的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 集群內Service-Cluster IP
上述的Pod雖然實現了集群內部互相通信,但是Pod是不穩定的,比如通過Deployment管理Pod,隨時可能對Pod進行擴縮容,這時候Pod的IP地址是變化的。這就希望能夠有一個固定的IP,使得集群內能夠訪問。
也就是前面在架構描述的時候所提到的,能夠把相同或者具有關聯的Pod,打上Label,組成一個Service。由Service提供固定的IP訪問Pod集群。這樣一來,不管Pod怎么創建和銷毀,都可以通過不變的Service IP進行訪問(這點其實跟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)創建一個有3個副本的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:可以發現目前并沒有關于whoami的service
在集群內可以通過任一節點訪問whoami的Pod
(3)創建對應的Service
kubectl expose deployment whoami-deployment??
發現有一個Cluster IP類型的service,名稱為whoami-deployment,IP地址為10.100.14.56
(4)通過對應的Cluster IP訪問
這里的ClusterIP只能供集群內部訪問
不難看出該service對三個pod實現了負載均衡
(5)具體查看一下whoami-deployment的詳情信息,發現有一個Endpoints連接了具體3個Pod
[root@m ~]# kubectl describe svc whoami-deployment
擴容后,service里的Endpoints的Pod信息也會發生變化
[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的創建除了前面的命令行kubectl expose的形式,還有yaml的方式
apiVersion: v1 kind: Service metadata:name: my-service spec:selector:app: MyAppports:- protocol: TCPport: 80targetPort: 9376type: Cluster4.外部服務訪問集群中的Pod
4.1 Service-NodePort
Service的一種類型,可以通過NodePort的方式讓外部服務訪問集群的Pod
因為外部是能夠訪問到集群機器的物理機器IP,所以NodePort就是在集群中每臺物理機器Node上暴露一個相同的IP,然后暴露一個端口將集群中的Pod映射到對應的端口
(1)創建一個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)創建NodePort類型的service,名稱為whoami-deployment
kubectl expose deployment whoami-deployment --type=NodePort
通過NodePort將容器內部的8000端口映射到了宿主機的32717端口
注意:從請求的結果可以看出,雖然集群的每個Node都開放了一個端口供外部訪問service,但哪怕請求同一個ip:port,其內部也是實現了負載均衡的
結論:NodePort雖然能夠實現外部訪問Pod的需求,但其實不好,因為會占用了各個物理主機上的端口(3個Node就會在3臺Node上各占用一個端口)
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就是幫助我們訪問集群內的服務
ingress包括:ingress controller和ingress resources
ingress controller:核心是一個deployment,實現方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,需要編寫的yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的類型可以是NodePort或者LoadBalancer。
ingress resources:這個就是一個類型為Ingress的k8s api對象了,這部分面向開發人員,用來配置一些映射規則
Ingress就相當于一個負載均衡器,是k8s對反向代理的一個抽象。大概的工作原理類似于Nginx,可以理解成在 Ingress 里建立一個個映射規則 , Ingress Controller?通過監聽 Ingress?這個api對象里的配置規則并轉化成 Nginx 的配置?, 然后對外部提供服務。
之所以需要分成ingress-controller和ingress resources,我覺得是由于網關部分的功能,大部分的組件都幫我們實現了,所以ingress直接提供controller接口,讓廠商去實現負載均衡等網關功能,使用方只需要關注映射配置了(相當于把Nginx里的配置拿出來在yaml里進行配置,不需要進入容器內去修改配置文件)
https://github.com/kubernetes/ingress-nginx
https://kubernetes.github.io/ingress-nginx/
(1)先定義我們要運行的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方式創建Ingress Nginx Controller ?Pod
可以通過Service的NodePort或者HostPort方式讓外界訪問到,這里選擇HostPort,比如指定worker01運行該Pod(給Node打標簽,然后在指定標簽的Node上運行)
對應的mandatory.yaml下載:https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
安裝指導:https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md
# 確保nginx-controller運行到w1節點上 kubectl label node w1 name=ingress # 使用HostPort方式運行,需要增加配置 hostNetwork: truenginx-ingress-controller在w1啟動成功
(3) 定義ingress規則
#ingress 訪問tomcat.chenpp.com的默認路徑,轉發到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)文件下添加對應的域名映射:
打開瀏覽器訪問成功
如果以后想要使用Ingress網絡,其實只要定義ingress和service和pod即可,前提是要保證nginx ingress controller已經配置好了。
在使用ingress的時候,如果發現當pod和nginx-ingress-controller不在一個節點上無法訪問時,可以設置下iptables,設置允許端口轉發: iptables -P FORWARD? ACCEPT或者如下圖讓pod和ingress在一個節點上也可以
XXXXspec: containers: - name: tomcatimage: tomcatports: - containerPort: 8080nodeSelector:name: ingress?
總結
以上是生活随笔為你收集整理的kubernetes(三)k8s中通信和Service的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: kubernetes(二)k8s组件
- 下一篇: kubernetes(八)问题排查