kubernetes实践(五)pod的网络通信

By prince No comments

一.pods的通信

1.集群内同一Pod内的容器通信

在同一个Pod内的容器共享同一个网络命名空间,共享同一个Linux协议栈。所以对于网络的各类操作,就和它们在同一台机器上一样,它们可以用localhost地址直接访问彼此的端口。其实这和传统的一组普通程序运行的环境是完全一样的,传统的程序不需要针对网络做特别的修改就可以移植了。这样做的结果是简单、安全和高效,也能减少将已经存在的程序从物理机或者虚拟机移植到容器下运行的难度。

 

2.集群内pod之间的通信

(1)两个pod在同一台主机

Pod1与Pod2在同一台主机。Pod1和Pod2在同一台主机的话,由Docker0网桥直接转发请求到Pod2,不需要经过Flannel。

(2)两个pod不在同一台主机

Pod的地址是与docker0在同一个网段的,但docker0网段与宿主机网卡是两个完全不同的IP网段,并且不同Node之间的通信只能通过宿主机的物理网卡进行。将Pod的IP和所在Node的IP关联起来,通过这个关联让Pod可以互相访问。

二.Service的通信

1.Service的基本操作

(1)创建service

a.创建nginx_service.yaml文件

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx

b.根据nginx_service.yaml文件创建service

kubectl apply -f nginx_deployment.yaml

(2)查询service列表

#查询所有命名空间service资源
kubectl get svc --all-namespaces -o wide

#查询默认命名空间service资源
kubectl get svc -o wide

#查询指定命名空间service资源
kubectl get svc -o wide -n namespace

(3)查询service详细信息

#查询默认命名空间service详细信息
kubectl describe deployment nginx-service

#查询指定命名空间service详细信息
kubectl describe deployment nginx-service -n namespace

(4)删除service

kubectl delete -f nginx_service.yaml

kubectl delete service nginx-service
2.Service的类型

(1)Service-Cluster IP

对于上述的Pod虽然实现了集群内部互相通信,但是Pod是不稳定的,比如通过Deployment管理Pod,随时可能对Pod进行扩缩容,这时候Pod的IP地址是变化的。能够有一个固定的IP,使得集群内能够访问。也就是之前在架构描述的时候所提到的,能够把相同或者具有关联的Pod,打上Label,组成Service。而Service有固定的IP,不管Pod怎么创建和销毁,都可以通过Service的IP进行访问

ClusterIP 给你一个集群内的服务,集群内的其它应用都可以访问该服务。集群外部无法访问它。

ClusterIP 服务的 YAML 文件类似如下:

apiVersion: v1
kind: Service
metadata:  
  name: my-internal-service
selector:    
  app: my-app
spec:
  type: ClusterIP
  ports:  
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP

(2)Service-NodePort IP

 NodePort 服务是引导外部流量到你的服务的最原始方式。NodePort,正如这个名字所示,在所有节点(虚拟机)上开放一个特定端口,任何发送到该端口的流量都被转发到对应服务。

NodePort 服务的 YAML 文件类似如下:

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

NodePort 服务主要有两点区别于普通的“ClusterIP”服务。第一,它的类型是“NodePort”。有一个额外的端口,称为 nodePort,它指定节点上开放的端口值 。如果你不指定这个端口,系统将选择一个随机端口。

NodePort虽然能够实现外部访问Pod的需求,但是真的好吗?其实不好,占用了各个物理主机上的端口, 而且用户自己来选择可用端口代价太大。

何时使用这种方式?

这种方法有许多缺点:

a.每个端口只能是一种服务
b.端口范围只能是 30000-32767
c.如果节点/VM 的 IP 地址发生变化,你需要能处理这种情况。

基于以上原因,我不建议在生产环境上用这种方式暴露服务。如果你运行的服务不要求一直可用,或者对成本比较敏感,你可以使用这种方法。这样的应用的最佳例子是 demo 应用,或者某些临时应用。

(3)Service-LoadBalance

LoadBalancer 服务是暴露服务到 internet 的标准方式。在 GKE 上,这种方式会启动一个 Network Load Balancer,它将给你一个单独的 IP 地址,转发所有流量到你的服务。

通常需要第三方云提供商支持,有约束性

何时使用这种方式?

如果你想要直接暴露服务,这就是默认方式。所有通往你指定的端口的流量都会被转发到对应的服务。它没有过滤条件,没有路由等。这意味着你几乎可以发送任何种类的流量到该服务,像 HTTP,TCP,UDP,Websocket,gRPC 或其它任意种类。

这个方式的最大缺点是每一个用 LoadBalancer 暴露的服务都会有它自己的 IP 地址,每个用到的 LoadBalancer 都需要付费,这将是非常昂贵的

(4)Ingress

有别于以上所有例子,Ingress 事实上不是一种服务类型。相反,它处于多个服务的前端,扮演着“智能路由”或者集群入口的角色。

你可以用 Ingress 来做许多不同的事情,各种不同类型的 Ingress 控制器也有不同的能力。

GKE 上的默认 ingress 控制器是启动一个 HTTP(S) Load Balancer。它允许你基于路径或者子域名来路由流量到后端服务。例如,你可以将任何发往域名 foo.yourdomain.com 的流量转到 foo 服务,将路径 yourdomain.com/bar/path 的流量转到 bar 服务。

这里我们选用Ingress Nginx Controller举例

Nginx Ingress Controller:https://kubernetes.github.io/ingress-nginx/

a.安装nginx-controller

#下载mandatory.yaml文件

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.29.0/deploy/static/mandatory.yaml
# 使用HostPort方式运行,需要在mandatory.yaml中增加配置
hostNetwork: true
# 确保nginx-controller运行到w1节点上
设置w1的lablel为name=ingress
kubectl label node w1 name=ingress
修改文件选择name=ingress的node运行也就是w1
nodeSelector:
   name: ingress
确保w1节点上的80和443端口没有被占用
修改后的部分文件
...
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      # wait up to five minutes for the drain of connections
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      hostNetwork: true
      nodeSelector:
        name: ingress
        kubernetes.io/os: linux
...
#执行安装nginx-ingress-controller
kubectl apply -f mandatory.yaml
b.运行tomcat 的node,deployment,service,ingress
#创建yaml文件tomcat.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
  labels:
    app: tomcat
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: tomcat
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  ports:
  - port: 80   
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomcat
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  rules:
  - host: tomcat.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: tomcat-service
          servicePort: 80

#执行安装

kubectl apply -f tomcat.yaml

#查询ingress

kubectl get ingress

#查询nginx-ingress详情

kubectl describe ingress nginx-ingress

#修改win的hosts文件,添加dns解析

192.168.50.15 tomcat.example.com

总结:如果以后想要使用Ingress网络,其实只要定义ingress,service和pod即可,前提是要保证nginx ingress controller已经配置好了。

发表评论

 

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据