首先考虑四个问题
思考:pod内部的容器是如何通信的?
思考:同一个节点中的pod是如何通信的?
思考:不同节点中的pod是如何通信的?
思考:pod如何对外网提供服务?
1.容器到容器(pod内部)的通信
同一个Pod内的容器(Pod内的容器是不会跨宿主机的)共享同一个网络命名空间,共享同一个Linux协议栈。所以对于网络的各类操作,就和它们在同一台机器上一样,它们甚至可以用localhost地址访问彼此的端口。
例如 如果容器2运行的是MySQL,那么容器1使用 localhost:3306就能直接访问这个运行在容器2上的MySQL了。
2.Pod之间的通信
每一个Pod都有一个真实的全局IP地址,同一个Node内的不同 Pod之间可以直接采用对方Pod的IP地址通信 。
Pod容器既有可能在同一个Node上运行,也有可能在不同的Node 上运行,所以通信也分为两类:同一个Node内Pod之间的通信和不同Node内Pod之间的通信。
2.1 同一个Node内Pod之间的通信
对于在同一台机器上的两个Pod来说,都是连接到同一个docker0网桥上,它们的IP地址IP1、IP2都是从docker0网段上动态获取的,它们和网桥本身的IP3是同一个网段的,Pod1和Pod2处于同一局域网内,它们之间可以通过docker0作为路由进行通信。
对于web app1访问web app2,他们都是连接到docker0上面的,它们是同一个网段的,web app1和web app2处于同一局域网内,它们之间可以通过docker0作为路由进行通信。
2.2 不同 Node上Pod之间的通信
那么一个网络报文请求是怎么从一个容器发送到另外一个容器的呢?例如从master1上的Container1容器(IP:10.244.0.13)访问node1上面Container2容器(IP:10.244.1.14)容器。
- Container1容器10.244.0.13直接访问目标容器Container2的IP 10.244.1.14,请求默认通过容器内部的eth0网卡发送出去。
- 请求报文通过Veth pair(虚拟设备对)被发送到Docker宿主机VethXXX设备上。
- 然后查找Docker宿主机的路由表信息,同时外部容器IP的报文都会转发到Flannel0虚拟网卡,这是一个P2P的虚拟网卡,然后报文就被转发到监听在另一端的Flanneld进程。
- 因为Flannel在Etcd中存储着子网和宿主机ip的对应关系,所以能够找到10.244.1.14对应的宿主机IP为11.101.1.3,进而开始组装UDP数据包发送数据到目的主机。
- 这个请求得以完成的原因每个节点上都启动着一个Flanneld udp进程,都监听着8285端口,所以master1通过Flanneld进程把数据包通过宿主机的Interface网卡发送给node1的Flanneld进程的相应端口即可。
- 请求报文到达node1之后,继续往上传输,到传输层,交给监听在8285端口的Flanneld程序处理。
- 请求数据被解包,然后发送给Flannel0虚拟网卡。
- 查找路由表,发现对应容器的报文要交给Docker0
- Docker0找到连到自己的容器,把报文发送给Container2,反之同样的工作方式。
3.pod如何对外网提供服务
3.1 通过端口映射的方式直接实现pod和外界资源的联系
这种方法就是在创建容器的时候将端口进行一个映射
在访问的时候直接访问宿主机IP+端口就行
3.2 通过service访问pod
每个 Pod 都有自己的 IP 地址。当 controller 用新 Pod 替代发生故障的 Pod 时,新 Pod 会分配到新的 IP 地址。这样就产生了一个问题:
如果一组 Pod 对外提供服务(比如 HTTP),它们的 IP 很有可能发生变化,那么客户端如何找到并访问这个服务呢?Kubernetes 给出的解决方案是 Service
3.2.1 NodePort
原理是Kubernetes会在每一个Node上暴露出一个端口:nodePort,外部网络可以通过(任一Node)[NodeIP]:[NodePort]访问到后端的Service。
[root@master1 ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx NodePort 10.10.127.106 <none> 88:31958/TCP 2m47s
访问192.168.1.81:31958
3.2.2 LoadBalance
将服务的类型设置成LoadBalance, NodePort类型的一 种扩展,这使得服务可以通过一个专用的负载均衡器来访问, 这是由Kubernetes中正在运行的云基础设施提供的。 负载均衡器将流量重定向到跨所有节点的节点端口。客户端通过负载均衡器的 IP 连接到服务。
3.2.3 ingress
创建一个Ingress资源, 这是一个完全不同的机制, 通过一 个IP地址公开多个服务,就是一个网关入口
下面详细介绍ingress-traefik
4.Traefik 概念
由于微服务架构以及 Docker 技术和 kubernetes 编排工具最近几年才开始逐渐流行,所以一开始的反向代理服务器比如Nginx、Apache 并未提供其支持,毕竟他们也不是先知,所以才会出现 Ingress Controller 这种东西来做 kubernetes 和前端负载均衡器如 Nginx之间做衔接。
Traefik是一款开源的反向代理与负载均衡工具。它最大的优点是能够与常见的微服务系统直接整合,可以实现自动化动态配置。
Traefik 天生就是提供了对 kubernetes 的支持,也就是说 Traefik本身就能跟 kubernetes API 交互,感知后端变化,因此可以得知: 在使用 traefik 时,Ingress Controller 已经没有用
4.1 Traefik布置
4.1.1 Traefik rbac验证配置
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses/status
verbs:
- update
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system
[root@master1 Traefik]# kubectl apply -f rbac.yaml
clusterrolebinding.rbac.authorization.k8s.io/traefik-ingress-controller created
4.2 创建traefik
traefik-deployment.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: kube-system
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
replicas: 1
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
containers:
- image: traefik:v1.7
name: traefik-ingress-lb
ports:
- name: http
containerPort: 80
- name: admin
containerPort: 8080
args:
- --api
- --kubernetes
- --logLevel=INFO
---
kind: Service
apiVersion: v1
metadata:
name: traefik-ingress-service
namespace: kube-system
spec:
type: NodePort
selector:
k8s-app: traefik-ingress-lb
ports:
- protocol: TCP
port: 80
name: web
targetPort: 80
- protocol: TCP
port: 8080
name: admin
[root@master1 Traefik]# kubectl apply -f traefik-deployment.yaml
serviceaccount/traefik-ingress-controller created
deployment.apps/traefik-ingress-controller created
service/traefik-ingress-service created
[root@master1 Traefik]#
[root@master1 Traefik]# kubectl get pods --namespace=kube-system|grep tra
traefik-ingress-controller-6b7f594d46-6q68w 1/1 Running 0 93s
[root@master1 Traefik]#
[root@master1 Traefik]# kubectl get service --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
traefik-ingress-service NodePort 10.10.55.63 <none> 80:62629/TCP,8080:11046/TCP 2m
[root@master1 Traefik]#
[root@master1 Traefik]# kubectl get svc --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.10.0.10 <none> 53/UDP,53/TCP,9153/TCP 27h
traefik-ingress-service NodePort 10.10.55.63 <none> 80:62629/TCP,8080:11046/TCP 6m9s
[root@master1 Traefik]#
4.3 部署 Ingress规则
实现域名对应Service名称
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: v1-net
spec:
rules:
- host: v1.net
http:
paths:
- path: /
backend:
serviceName: v1-net
servicePort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: v2-net
spec:
rules:
- host: v2.net
http:
paths:
- path: /
backend:
serviceName: v2-net
servicePort: 80
[root@master1 Traefik]# kubectl apply -f traefik-ingress.yaml
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/v1-net created
ingress.extensions/v2-net created
[root@master1 Traefik]#
5.创建pod容器并配置service
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: v1-net
name: v1-net
spec:
replicas: 1
selector:
matchLabels:
app: v1-net
template:
metadata:
labels:
app: v1-net
spec:
containers:
- image: nginx:alpine
name: nginx
---
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: v1-net
name: v1-net
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: v1-net
status:
loadBalancer: {}
[root@master1 yaml]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ngx-795b46448d-d49mg 1/1 Running 0 20h
v1-net-89cffdd7-x97kl 1/1 Running 0 10m
[root@master1 yaml]#
6.查看traefik-ingress-service 的端口映射
[root@master1 yaml]# kubectl get svc --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.10.0.10 <none> 53/UDP,53/TCP,9153/TCP 28h
traefik-ingress-service NodePort 10.10.55.63 <none> 80:62629/TCP,8080:11046/TCP 44m
[root@master1 yaml]#
7.域名的绑定
192.168.199.120 v1.net v2.net
实现了在客户端的访问 但是必须访问的是映射后的端口
8.修改端口
查看如上Service,Nodeport端口为62629,即访问虚拟主机需要带上该端口,如何将其端口修改为80端口呢。
vim /etc/kubernetes/manifests/kube-apiserver.yaml
在 command下添加 如下代码即可;
- –service-node-port-range=1-65535
重启apiserver服务即可:
docker ps |grep apiserver |awk ‘{print $1}’|xargs docker restart
kubectl edit svc traefik-ingress-service --namespace=kube-system