四、Kubernetes 网络模型

1、Network

接下来就要说到跟Kubernetes网络通信相关的内容,我们都知道K8S最小的操作单位是Pod,而我们在前面章节说过同一个Pod中多个容器通信是默认就已经支持了的。但是怎么支持的没去解释,下面就开始说明各种情况下的容器是如何通信的。

1.1 集群内部通信

1.1.1 同一个 Pod 中的容器通信

因为一个 Pod 是存在一台机器中的,不可能说 Pod 里的容器会存到不同机器的,而同一台机器中的Container想要通信肯定是很方便的。

在前面章节演示中,我们知道每一个Pod中都一定会有一个 Pause Container,这个Container就是同一个Pod中其他Container通信的桥梁,其他Container在创建完成之后都会与Pause Container建立连接,于是它们就有了共同的网段,从而实现了通信!

  • 理解 Pause Container

    • 在Kubernetes Pod中,首先创建一个基础结构或 “Pause” 容器来托管容器端点
    • 属于同一 Pod 的容器(包括基础结构容器和工作容器)共享一个公共的网络名称空间和终结点(相同的IP和端口空间)
      • 它会在每个 Pod 里,额外起一个 Infra container 小容器来共享整个 Pod 的 Network Namespace。
    • 其他所有容器都会通过 Join Namespace 的方式加入到 Infra container 的 Network Namespace 中。
      • 所以说一个 Pod 里面的所有容器,它们看到的网络视图是完全一样的。
    • 需要 Pause 容器来容纳工作容器崩溃或重新启动而不会丢失任何网络配置
  • 案例测试

    • 准备 yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx-deployment
        labels:
          app: nginx
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - name: nginx
              image: nginx:1.7.9
              ports:
              - containerPort: 80
      
    • 创建资源

      [root@master-kubeadm-k8s deployment]# kubectl apply -f nginx_deployment.yaml
      deployment.apps/nginx-deployment created
      
      # Pod 分布在 worker01 和 worker02 中,我们选择一个node去看一下
      [root@master-kubeadm-k8s deployment]# kubectl get pods -o wide
      NAME                               READY   STATUS    RESTARTS   AGE     IP               NODE                   NOMINATED NODE   READINESS GATES
      nginx-deployment-6dd86d77d-2sm56   1/1     Running   0          8m44s   192.168.14.17    worker01-kubeadm-k8s              
      nginx-deployment-6dd86d77d-dh5hj   1/1     Running   0          8m44s   192.168.14.16    worker01-kubeadm-k8s              
      nginx-deployment-6dd86d77d-zk8ms   1/1     Running   0          8m44s   192.168.221.76   worker02-kubeadm-k8s              
      
    • worker01 节点查看容器

      [root@worker01-kubeadm-k8s ~]# docker ps | grep nginx
      b918c5aa0352        84581e99d807           "nginx -g 'daemon of…"   About a minute ago   Up About a minute                       k8s_nginx_nginx-deployment-6dd86d77d-2sm56_default_fde4c80d-70ea-11ea-937b-5254008afee6_0
      54de85908726        84581e99d807           "nginx -g 'daemon of…"   About a minute ago   Up About a minute                       k8s_nginx_nginx-deployment-6dd86d77d-dh5hj_default_fe03776c-70ea-11ea-937b-5254008afee6_0
      889f8517be18        k8s.gcr.io/pause:3.1   "/pause"                 About a minute ago   Up About a minute                       k8s_POD_nginx-deployment-6dd86d77d-dh5hj_default_fe03776c-70ea-11ea-937b-5254008afee6_0
      fbe190cf8c77        k8s.gcr.io/pause:3.1   "/pause"                 About a minute ago   Up About a minute                       k8s_POD_nginx-deployment-6dd86d77d-2sm56_default_fde4c80d-70ea-11ea-937b-5254008afee6_0
      

      因为 worker01 节点被分配了两个 Pod,所以这里也就有2个容器存在,以及2个 Pause 容器分别属于2个Pod。

1.1.2 集群内 Pod 之间的通信

接下来就聊聊K8S最小的操作单元,Pod之间的通信,我们知道Pod会有独立的IP地址,这个IP地址是被Pod中所有的Container共享的,那多个Pod之间的通信能通过这个IP地址吗?

这里可能会想到需要分两个维度去验证:

  • 集群中同一台机器中的Pod
  • 集群中不同机器中的Pod

但是我们无需分成两个维度去验证,因为在 K8S网络模型 中,集群内所有 Pod 默认都是可以直接通信的。因为有网络插件的存在,我们的案例中使用的插件是 Calico ,它已经帮我们完成了所有的准备。

  • 官方对K8S网络模型的介绍

    • 每个人Pod都有自己的IP地址。这意味着无需显式地在它们之间创建链接,Pods并且几乎不需要处理将容器端口映射到主机端口的问题。

    • 这将创建一个干净的,向后兼容的模型,Pods从端口分配,命名,服务发现,负载平衡,应用程序配置和迁移的角度来看,该模型可以像VM或物理主机一样对待。

  • Kubernetes对任何网络实施都施加以下基本要求(除非有任何故意的网络分段策略):

    • 节点上的Pod可以与所有节点上的所有Pod通信,而无需NAT

    • 节点上的代理(例如系统守护程序,kubelet)可以与该节点上的所有pod通信

    • 节点主机网络中的Pod可以与所有节点上的所有Pod通信,而无需NAT

  • 案例验证

    • 编写 nginx_network.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx-deployment
        labels:
          app: nginx
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - name: nginx
              image: nginx:1.7.9
              ports:
              - containerPort: 80
      
    • 创建资源

      [root@master-kubeadm-k8s test_network1]# kubectl apply -f nginx_network.yaml
      deployment.apps/nginx-deployment created
      
      # 查看 Pod 分配的节点以及所分配的ip
      [root@master-kubeadm-k8s test_network1]# kubectl get pods -o wide
      NAME                               READY   STATUS    RESTARTS   AGE   IP               NODE                   NOMINATED NODE   READINESS GATES
      nginx-deployment-6dd86d77d-rfgnq   1/1     Running   0          16s   192.168.14.19    worker01-kubeadm-k8s              
      nginx-deployment-6dd86d77d-xf2j6   1/1     Running   0          16s   192.168.221.78   worker02-kubeadm-k8s              
      nginx-deployment-6dd86d77d-zx897   1/1     Running   0          16s   192.168.221.79   worker02-kubeadm-k8s              
      
    • 进入容器测试通信

      # 进入worker01节点的容器
      [root@worker01-kubeadm-k8s ~]# docker exec -it f8693040e28d bash
      
      # 查看当前容器的IP
      root@nginx-deployment-6dd86d77d-rfgnq:/# ip a
      # ...省略其他组件...
      4: eth0@if11:  mtu 1440 qdisc noqueue state UP
          link/ether 02:35:73:f0:76:83 brd ff:ff:ff:ff:ff:ff
          inet 192.168.14.19/32 scope global eth0
             valid_lft forever preferred_lft forever
      
      # ping worker02节点中Pod的 IP,是可以正常ping通的
      root@nginx-deployment-6dd86d77d-rfgnq:/# ping 192.168.221.78
      PING 192.168.221.78 (192.168.221.78): 48 data bytes
      56 bytes from 192.168.221.78: icmp_seq=0 ttl=62 time=4.273 ms
      56 bytes from 192.168.221.78: icmp_seq=1 ttl=62 time=1.438 ms
      ^C--- 192.168.221.78 ping statistics ---
      2 packets transmitted, 2 packets received, 0% packet loss
      round-trip min/avg/max/stddev = 1.438/2.855/4.273/1.418 ms
      
1.1.3 集群内 Service-Cluster IP

对于上述的Pod虽然实现了集群内部互相通信,但是Pod是不稳定的,比如通过Deployment管理Pod,随时可能对Pod进行扩缩容,这时候Pod的IP地址是变化的。

能够有一个固定的IP,使得集群内能够访问。也就是之前在架构描述的时候所提到的,能够把相同或者具有关联的Pod,打上Label,组成 Service。而Service有固定的IP,不管Pod怎么创建和销毁,都可以通过Service的IP进行访问。

  • 理解 Service

    • Service 是将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法
    • Service 定义了这样一种抽象:逻辑上的一组 Pod,一种可以访问它们的策略,通常称为微服务。
    • 这一组 Pod 能够被 Service 访问到,通常是通过 selector 实现的。
  • 使用 Service

    • 编写 whoami-deployment.yaml

      whoami 这个应用是用来查看当前访问的是哪台机器的

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: whoami-deployment
        labels:
          app: whoami
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: whoami
        template:
          metadata:
            labels:
              app: whoami
          spec:
            containers:
            - name: whoami
              image: jwilder/whoami
              ports:
              - containerPort: 8000
      
    • 创建资源

      [root@master-kubeadm-k8s whoami]# kubectl apply -f whoami-deployment.yaml
      deployment.apps/whoami-deployment created
      
    • 查看 Pod 与 Service

      [root@master-kubeadm-k8s whoami]# kubectl get pods -o wide
      NAME                                 READY   STATUS    RESTARTS   AGE     IP               NODE                   NOMINATED NODE   READINESS GATES
      whoami-deployment-678b64444d-7nr87   1/1     Running   0          2m24s   192.168.221.80   worker02-kubeadm-k8s              
      whoami-deployment-678b64444d-hpnm5   1/1     Running   0          2m24s   192.168.14.20    worker01-kubeadm-k8s              
      whoami-deployment-678b64444d-mfhz4   1/1     Running   0          2m24s   192.168.14.21    worker01-kubeadm-k8s              
          
      # 发现并没有 whoami 的service
      [root@master-kubeadm-k8s whoami]# kubectl get svc
      NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
      kubernetes   ClusterIP   10.96.0.1            443/TCP   4d
      
    • 验证通信

      # 直接访问是没问题的
      [root@master-kubeadm-k8s whoami]# curl 192.168.221.80:8000
      I'm whoami-deployment-678b64444d-7nr87
      [root@master-kubeadm-k8s whoami]# curl 192.168.14.20:8000
      I'm whoami-deployment-678b64444d-hpnm5
      [root@master-kubeadm-k8s whoami]# curl 192.168.14.21:8000
      I'm whoami-deployment-678b64444d-mfhz4
      
    • 创建 whoami 的 Service

      • YAML文件方式

        apiVersion: v1
        kind: Service             # 定义资源类型为 Service
        metadata:
          name: whoami-service
        spec:
          selector:
            app: whoami               # 选取具有label为 app: whoami 的Pod
          ports:
            - protocol: TCP           # 协议为 TCP
              port: 80                # 映射端口为80
              targetPort: 8000        # 目标端口为8000
        
      • 命令方式

        # 注意:使用命令来创建 Service,名称要与资源名称一致 whoami-deployment,否则会创建失败
        [root@master-kubeadm-k8s whoami]# kubectl expose deployment whoami-deployment --port=80 --target-port=8000
        service/whoami-deployment exposed
        
        # 失败案例
        [root@master-kubeadm-k8s whoami]# kubectl expose deployment whoami-service --port=80 --target-port=8000
        Error from server (NotFound): deployments.extensions "whoami-service" not found
        
    • 再次查看 Service

      # 新创建的service已经存在了,ClusterIP为 10.103.138.245, 映射端口为 80, selector选取的label为 app=whoami
      [root@master-kubeadm-k8s whoami]# kubectl get svc -o wide
      NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE     SELECTOR
      kubernetes       ClusterIP   10.96.0.1                443/TCP   4d      
      whoami-service   ClusterIP   10.103.138.245           80/TCP    2m14s   app=whoami
      
    • 通过 Service-Cluster IP 访问 whoami

      # 直接访问 Service-Cluster IP 可以自动帮我们负载均衡到每一个 Pod 上
      [root@master-kubeadm-k8s whoami]# curl 10.103.138.245
      I'm whoami-deployment-678b64444d-7nr87
      [root@master-kubeadm-k8s whoami]# curl 10.103.138.245
      I'm whoami-deployment-678b64444d-mfhz4
      [root@master-kubeadm-k8s whoami]# curl 10.103.138.245
      I'm whoami-deployment-678b64444d-7nr87
      [root@master-kubeadm-k8s whoami]# curl 10.103.138.245
      I'm whoami-deployment-678b64444d-hpnm5
      
    • 查看 whoami-service的详情信息

      [root@master-kubeadm-k8s whoami]# kubectl describe svc whoami-service
      Name:              whoami-service
      Namespace:         default
      Labels:            app=whoami
      Annotations:       
      Selector:          app=whoami
      Type:              ClusterIP
      IP:                10.100.125.194
      Port:                80/TCP
      TargetPort:        8000/TCP
      
      # 发现有一个Endpoints连接了具体3个Pod
      Endpoints:         192.168.14.20:8000,192.168.14.21:8000,192.168.221.80:8000
      Session Affinity:  None
      Events:            
      
    • 测试扩缩容

      # 将 whoami 扩容为 5 个
      [root@master-kubeadm-k8s whoami]# kubectl scale deployment whoami-deployment --replicas=5
      deployment.extensions/whoami-deployment scaled
      
      # 再次查看 whoami-service 详情
      [root@master-kubeadm-k8s whoami]# kubectl describe svc whoami-service
      Name:              whoami-service
      Namespace:         default
      Labels:            app=whoami
      Annotations:       
      Selector:          app=whoami
      Type:              ClusterIP
      IP:                10.100.125.194
      Port:                80/TCP
      TargetPort:        8000/TCP
      
      # 发现这里多了 +2 more... 表示又多了2个新的 Pod
      Endpoints:         192.168.14.20:8000,192.168.14.21:8000,192.168.14.22:8000 + 2 more...
      Session Affinity:  None
      Events:            
      
    • 再次测试功能

      # 可以负载均衡到 5 个 容器了
      [root@master-kubeadm-k8s whoami]# curl 10.104.9.131
      I'm whoami-deployment-678b64444d-nzqkp
      [root@master-kubeadm-k8s whoami]# curl 10.104.9.131
      I'm whoami-deployment-678b64444d-7nr87
      [root@master-kubeadm-k8s whoami]# curl 10.104.9.131
      I'm whoami-deployment-678b64444d-hlpfp
      [root@master-kubeadm-k8s whoami]# curl 10.104.9.131
      I'm whoami-deployment-678b64444d-nzqkp
      [root@master-kubeadm-k8s whoami]# curl 10.104.9.131
      I'm whoami-deployment-678b64444d-mfhz4
      [root@master-kubeadm-k8s whoami]# curl 10.104.9.131
      I'm whoami-deployment-678b64444d-hpnm5
      
    四、Kubernetes 网络模型_第1张图片
    Service.png

其实Service存在的意义就是为了Pod的不稳定性,而上述探讨的就是关于Service的一种类型Cluster IP,只能供集群内访问。

以Pod为中心,已经讨论了关于集群内的通信方式,接下来就是探讨集群中的Pod访问外部服务,以及外部服务访问集群中的Pod。

1.2 集群外与集群内通信

1.2.1 Pod访问外部服务

这个其实没啥可说的,因为外部的网络只要是可以与互联网联通的IP,Pod就可以直接访问了。

# 进入容器
[root@worker01-kubeadm-k8s ~]# docker exec -it 4895fc61ec69 bash

# 访问外部 ip
root@nginx-deployment-6dd86d77d-dxx67:/# ping www.baidu.com
PING www.baidu.com (180.101.49.12): 48 data bytes
56 bytes from 180.101.49.12: icmp_seq=0 ttl=50 time=15.508 ms
56 bytes from 180.101.49.12: icmp_seq=1 ttl=50 time=10.436 ms
^C--- www.baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 10.436/12.972/15.508/2.536 ms
1.2.2 外部服务访问集群中的Pod
1.2.2.1 Service-NodePort

NodePort 也是Service的一种类型,可以通过NodePort的方式访问。因为外部能够访问到集群的物理机器IP,所以就是在集群中 每台物理机器上暴露一个相同的IP,比如32008。

  • 编写 whoami-nodePort.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whoami-deployment
      labels:
        app: whoami
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: whoami
      template:
        metadata:
          labels:
            app: whoami
        spec:
          containers:
          - name: whoami
            image: jwilder/whoami
            ports:
            - containerPort: 8000
    
  • 创建资源

    [root@master-kubeadm-k8s nodePort]# kubectl apply -f whoami-nodePort.yaml
    deployment.apps/whoami-deployment created
    
  • 创建 nodePort 类型的 Service

    • YAML文件方式

      apiVersion: v1
      kind: Service             # 定义资源类型为 Service
      metadata:
        name: whoami-service
      spec:
        selector:
          app: whoami               # 选取具有label为 app: whoami 的Pod
        ports:
          - protocol: TCP           # 协议为 TCP
            port: 80                # 映射端口为80
            targetPort: 8000        # 目标端口为8000
        type: NodePort          # 指定Service类型为 NodePort
      
    • 命令方式

      # 指定Service的类型为 NodePort
      [root@master-kubeadm-k8s nodePort]# kubectl expose deployment whoami-deployment --type=NodePort
      service/whoami-deployment exposed
      
  • 查看 Service

    # 新创建的 Service已经出来了,并且映射到宿主机的端口为 30184
    [root@master-kubeadm-k8s nodePort]# kubectl get svc
    NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
    kubernetes          ClusterIP   10.96.0.1                443/TCP          4d1h
    whoami-deployment   NodePort    10.101.187.169           8000:30184/TCP   6s
    
  • 测试功能

    # 访问宿主机的 ip + 映射端口, 成功访问到 Pod
    [root@master-kubeadm-k8s nodePort]# curl 192.168.50.111:30184
    I'm whoami-deployment-678b64444d-nhcpl
    [root@master-kubeadm-k8s nodePort]# curl 192.168.50.111:30184
    I'm whoami-deployment-678b64444d-wvwg2
    [root@master-kubeadm-k8s nodePort]# curl 192.168.50.111:30184
    I'm whoami-deployment-678b64444d-nhcpl
    [root@master-kubeadm-k8s nodePort]# curl 192.168.50.111:30184
    I'm whoami-deployment-678b64444d-djsx9
    
四、Kubernetes 网络模型_第2张图片
NodePort.png
> NodePort虽然能够实现外部访问Pod的需求,但是真的好吗?
>
> 其实不好,因为占用了各个物理主机上的端口。
1.2.2.1 Service-LoadBalance

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

  • Ingress

    • Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。
    • Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。
    • Ingress 公开了从集群外部到集群内 services 的HTTP和HTTPS路由。 流量路由由 Ingress 资源上定义的规则控制。
    • 可以将 Ingress 配置为提供服务外部可访问的 URL、负载均衡流量、终止 SSL / TLS 并提供基于名称的虚拟主机。
    • Ingress 控制器 通常负责通过负载均衡器来实现 Ingress
    • 简单来说,Ingress就是帮助我们访问集群内的服务的。
  • 环境准备

    要使用 Ingress 必须具有 ingress 控制器才能满足 Ingress 的要求。仅创建 Ingress 资源是无效的。

    • Ingress 控制器有很多,我们选择自己熟悉的即可

      • 可选的控制器
        • Nginx、HAProxy、Istio、KONG等等。。。
        • 我们这里使用:Ingress-nginx
    • 首先要加载 Ingress-nginx 资源

      Ingress-nginx 官网也有这样的步骤,如果网络好的话可以直接创建资源

      # 直接创建资源
      kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
      
      # 下载 yaml 文件
      [root@master-kubeadm-k8s ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
      --2020-03-29 06:30:17--  https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
      Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.108.133
      Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.108.133|:443... connected.
      HTTP request sent, awaiting response... 200 OK
      Length: 6635 (6.5K) [text/plain]
      Saving to: ‘mandatory.yaml’
      
      100%[====================================================================================================================================================================>] 6,635       2.65KB/s   in 2.4s
      
      2020-03-29 06:30:21 (2.65 KB/s) - ‘mandatory.yaml’ saved [6635/6635]
      
      # 看下这个 yaml 文件需要哪些镜像
      [root@master-kubeadm-k8s ~]# cat mandatory.yaml | grep image
                image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
      
      # 单独拉取,会有些慢,但我们可以看到进度,如果直接用官方的方式,我们就不知道进行到哪了
      root@master-kubeadm-k8s ~]# docker pull quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
      0.30.0: Pulling from kubernetes-ingress-controller/nginx-ingress-controller
      c9b1b535fdd9: Pull complete
      45ba4c948320: Downloading [==============>                                    ]  14.68MB/51.78MB
      70c24c20a569: Download complete
      58acda238271: Downloading [=======================================>           ]  14.54MB/18.51MB
      7873cb07ba91: Download complete
      3572b831a7ad: Waiting
      2e4b94d88c7a: Waiting
      73d054fe6162: Waiting
      72107c0475b3: Waiting
      0920fa00bdaf: Waiting
      bbc4231b0eed: Waiting
      1a0d8e7b84e8: Waiting
      
    • 设置Pod在指定节点创建

      # 先查看节点的名称
      [root@master-kubeadm-k8s ~]# kubectl get nodes
      NAME                   STATUS   ROLES    AGE     VERSION
      master-kubeadm-k8s     Ready    master   4d16h   v1.14.0
      worker01-kubeadm-k8s   Ready       4d16h   v1.14.0
      worker02-kubeadm-k8s   Ready       4d16h   v1.14.0
      
      # 在 master 节点给 worker01 节点打一个标签 name=ingress
      [root@master-kubeadm-k8s ~]# kubectl label node worker01-kubeadm-k8s name=ingress
      node/worker01-kubeadm-k8s labeled
      
      # 查看节点的labels,
      [root@master-kubeadm-k8s ~]# kubectl get nodes --show-labels
      NAME                   STATUS   ROLES    AGE     VERSION   LABELS
      master-kubeadm-k8s     Ready    master   4d16h   v1.14.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master-kubeadm-k8s,kubernetes.io/os=linux,node-role.kubernetes.io/master=
          
      # worker01 节点多了个name=ingress的label
      worker01-kubeadm-k8s   Ready       4d16h   v1.14.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker01-kubeadm-k8s,kubernetes.io/os=linux,name=ingress
      
      worker02-kubeadm-k8s   Ready       4d16h   v1.14.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker02-kubeadm-k8s,kubernetes.io/os=linux
      
    • 修改 YAML 文件,增加自定义的配置

      在 mandatory.yaml 文件中找到这一段

      # ...省略...
      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 # 表示使用HostPort方式运行,需要增加配置
            # ===========================
            nodeSelector:
              # ==========原来的文件中是没有这个配置的=================
              name: ingress # 表示选择 label为 name: ingress 的节点
              # ===========================
              kubernetes.io/os: linux
            containers:
              - name: nginx-ingress-controller
                image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
                args:
                  - /nginx-ingress-controller
                  - --configmap=$(POD_NAMESPACE)/nginx-configuration
                  - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
                  - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
                  - --publish-service=$(POD_NAMESPACE)/ingress-nginx
                  - --annotations-prefix=nginx.ingress.kubernetes.io
                securityContext:
                  allowPrivilegeEscalation: true
                  capabilities:
                    drop:
                      - ALL
                    add:
                      - NET_BIND_SERVICE
                  # www-data -> 101
                  runAsUser: 101
      # ...省略...
      
    • 创建 mandatory 资源

      [root@master-kubeadm-k8s ~]# kubectl apply -f mandatory.yaml
      namespace/ingress-nginx created
      configmap/nginx-configuration created
      configmap/tcp-services created
      configmap/udp-services created
      serviceaccount/nginx-ingress-serviceaccount created
      clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
      role.rbac.authorization.k8s.io/nginx-ingress-role created
      rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
      clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
      deployment.apps/nginx-ingress-controller created
      limitrange/ingress-nginx created
      
  • 创建 tomcat的 Pod 和Service

    • 编写 tomcat-hostPort.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
      ---                             # 同一个yaml文件中配置多个资源
      apiVersion: v1
      kind: Service
      metadata:
        name: tomcat-service
      spec:
        ports:
        - port: 80   
          protocol: TCP
          targetPort: 8080
        selector:
          app: tomcat                 # 选择label为 app: tomcat 的Pod
      
    • 创建资源

      [root@master-kubeadm-k8s hostPort]# kubectl apply -f tomcat-hostPort.yaml
      deployment.apps/tomcat-deployment created
      service/tomcat-service created
      
    • 查看资源

      # 查看 pods
      [root@master-kubeadm-k8s hostPort]# kubectl get pods
      NAME                                 READY   STATUS    RESTARTS   AGE
      tomcat-deployment-6b9d6f8547-6ltxl   1/1     Running   0          95s
      
      # 查看 Service
      [root@master-kubeadm-k8s hostPort]# kubectl get svc
      NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
      kubernetes       ClusterIP   10.96.0.1                443/TCP   4d17h
      tomcat-service   ClusterIP   10.101.241.112           80/TCP    7s
      
  • 创建 Ingress 以及定义转发规则

    • 编写 nginx-ingress.yaml

      #ingress
      apiVersion: networking.k8s.io/v1beta1   # 版本
      kind: Ingress                           # 定义资源类型为 Ingress
      metadata:
        name: nginx-ingress
      spec:
        rules:                                # 定义规则
        - host: tomcat.sunny.com              # 匹配的 域名为 tomcat.sunny.com
          http:
            paths:                            # 匹配的路径, 可配置多个规则
            - path: /                         # 表示访问根目录就会被匹配
              backend:
                serviceName: tomcat-service   # 要访问的 Service
                servicePort: 80               # 服务的端口(Service映射)
      
    • 创建资源

      [root@master-kubeadm-k8s hostPort]# kubectl apply -f nginx-ingress.yaml
      ingress.extensions/nginx-ingress created
      
    • 查看ingress

      # 可以看到这个ingress对外暴露的域名和端口
      [root@master-kubeadm-k8s hostPort]# kubectl get ingress
      NAME            HOSTS              ADDRESS   PORTS   AGE
      nginx-ingress   tomcat.sunny.com             80      122m
      
    • 修改 Windows 的Hosts文件

      192.168.50.112 tomcat.sunny.com
      
      # 测试能否通信
      C:\WINDOWS\system32>ping tomcat.sunny.com
      
      正在 Ping tomcat.sunny.com [192.168.50.112] 具有 32 字节的数据:
      来自 192.168.50.112 的回复: 字节=32 时间<1ms TTL=64
      来自 192.168.50.112 的回复: 字节=32 时间<1ms TTL=64
      
      192.168.50.112 的 Ping 统计信息:
          数据包: 已发送 = 2,已接收 = 2,丢失 = 0 (0% 丢失),
      往返行程的估计时间(以毫秒为单位):
          最短 = 0ms,最长 = 0ms,平均 = 0ms
      Control-C
      
  • 测试

    这里已经访问到 Tomcat了, 只是现在最新的 Tomcat 镜像里都是空的,没有应用,所以访问不到内容!

四、Kubernetes 网络模型_第3张图片
Test.png
四、Kubernetes 网络模型_第4张图片
HostPort.png

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

1.2.2.3 NodePort 与 HostPort 区别
  • NodePort会在每个集群节点上都开放端口,占用端口资源
  • HostPort只会在指定的某个节点开放端口,不会有端口资源浪费

你可能感兴趣的:(四、Kubernetes 网络模型)