Service 和 Ingress

文章目录

Service 和 Ingress

service 和 ingress 是kubernetes 中用来转发网络请求的两个服务,两个服务用处不同,service 主要提供集群内部网络调用、负载均衡(四层负载),ingress 提供外部访问,反向代理,负载均衡(七层负载)

Service

在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。

为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务

可以说 Service 是一个应用服务的抽象,定义了 Pod 逻辑集合和访问这个 Pod 集合的策略。Service 代理 Pod 集合,对外表现为一个访问入口,访问该入口的请求将经过负载均衡,转发到后端 Pod 中的容器。

Endpoint

每一个service 都会有一个 Endpoint controller , 在endponit 里面会维护 address,targetPort 和 容器之间的关系。整个访问链是 通过 service -> endpoint -iptables->kube-proxy -> 容器

service 的定义

Yaml 文件案例

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc  # service name
  labels:
    app: nginx-svc  # service 自己的标签
spec:
  ports:
  - name: http # service 端口配置的名称
    protocol: TCP # 端口绑定的协议,支持 TCP、UDP、SCTP,默认为 TCP
    port: 1080 # service 自己的端口
    targetPort: 80 # 目标 pod 的端口
  type: NodePort # 默认是ClusterIP 类型,只能在集群内部使用  
   	             # NodePort 用于将服务暴露给外部访问
  selector: # 选中当前 service 匹配哪些 pod,对哪些 pod 的东西流量进行代理
    app: nginx

使用命令

sh 复制代码
# 创建 service
kubectl create -f nginx-svc.yaml

# 查看 service 信息,通过 service 的 cluster ip 进行访问
kubectl get svc 

# 查看 pod 信息,通过 pod 的 ip 进行访问
kubectl get po -owide

# 创建其他 pod 通过 service name 进行访问(推荐)
kubectl exec -it busybox -- sh
curl http://nginx-svc

# 默认在当前 namespace 中访问,如果需要跨 namespace 访问 pod,则在 service name 后面加上 .<namespace> 即可
curl http://nginx-svc.default

代理集群外部服务

用于解决外部服务迁移到k8s 集群,各个环境访问名称统一,容器内部访问外部服务等需求

实现方式:

  1. 编写 service 配置文件时,不指定 selector 属性

    yaml 复制代码
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-svc  # service name
      labels:
        app: nginx-svc  # service 自己的标签
    spec:
      ports:
      - name: http # service 端口配置的名称
        protocol: TCP # 端口绑定的协议,支持 TCP、UDP、SCTP,默认为 TCP
        port: 1080 # service 自己的端口
        targetPort: 80 # 目标 pod 的端口
      type: ClusterIP # 默认是ClusterIP 类型,只能在集群内部使用  
       	             # NodePort 用于将服务暴露给外部访问
  2. 自己创建 endpoint

yaml 复制代码
apiVersion: v1
kind: Endpoints
metadata:
  labels:
    app: nginx-svc-external # 与 service 一致
  name: nginx-svc-external # 与 service 一致
  namespace: default # 与 service 一致
subsets:  # 子网设置
- addresses:
  - ip: <target ip> # 目标 ip 地址
  ports: # 与 service 一致
  - name: http  # service 中ports.name 属性保持一致
    port: 80
    protocol: TCP

反向代理外部域名

直接通过在容器内部直接通过外部域名去访问

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  labels:
    app: baidu-external-domain
  name: baidu-external-domain
spec:
  type: ExternalName
  externalName: www.baidu.com

Service 常用类型

Type 用途 补充
ClusterIP 只能在集群内部使用,不配置类型的话默认就是 ClusterIP
ExternalName 返回定义的 CNAME 别名,可以配置为域名
LoadBalancer 使用云服务商(阿里云、腾讯云等)提供的负载均衡器服务
NodePort 在所有安装了 kube-proxy 的节点都绑定一个端口,此端口可以代理至对应的 Pod,集群外部可以使用任意节点 ip + NodePort 的端口号访问到集群中对应 Pod 中的服务。 一般用于测试环境,生产环境使用ingress

补充:

NodePort 映射是一个O(N) 的时间复杂度,当节点数越多的时候,效率越低,内部代码是通过轮询来处理的

当类型设置为 NodePort 后,可以在 ports 配置中增加 nodePort 配置指定端口,需要在下方的端口范围内,如果不指定会随机指定端口

端口范围:30000~32767

端口范围配置在 /usr/lib/systemd/system/kube-apiserver.service 文件中

Ingress

Ingress 可以提供外网访问 Service 的能力。可以把某个请求地址映射、路由到特定的 service。

ingress 需要配合 ingress controller 一起使用才能发挥作用,ingress 只是相当于路由规则的集合而已,真正实现路由功能的,是 Ingress Controller,ingress controller 和其它 k8s 组件一样,也是在 Pod 中运行。

Ingress-nginx

Ingress 是一个更高层的抽象,具体实现还需要借助于Ingress controller 列如 Ingress-nginx 其他控制器参考 官网文档 https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress-controllers

安装

参考官网地址:https://kubernetes.github.io/ingress-nginx/deploy/#using-helm

官网默认采用helm,因此需要先安装helm

  1. 下载安装包 wget https://get.helm.sh/helm-v3.14.2-linux-amd64.tar.gz
  2. tar -zxvf helm-v3.2.3-linux-amd64.tar.gz
  3. cp helm /usr/local/bin/
sh 复制代码
# 添加ingree 仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

# 查看仓库列表
helm repo list

# 搜索 ingress-nginx
helm search repo ingress-nginx

# 下载安装包
helm pull ingress-nginx/ingress-nginx  --version 4.4.2

# 解压安装包
tar -zxvf ingress-nginx-4.4.2.tgz

# 解压后,进入解压完成的目录
cd ingress-nginx

# 修改 values.yaml
  镜像地址:修改为国内镜像
  registry: registry.cn-hangzhou.aliyuncs.com
  image: google_containers/nginx-ingress-controller
  image: google_containers/kube-webhook-certgen
  tag: 两个image 版本保持一致 或者 不动也行

  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet

  修改部署配置的 kind: /DaemonSet    # Deployment 改成 DaemonSet
  nodeSelector:
    ingress: "true" # 增加选择器,如果 node 上有 ingress=true 就部署

  将 admissionWebhooks.enabled 修改为 false
  
  将 service 中的 type 由 LoadBalancer 修改为 ClusterIP,如果服务器是云平台才用 LoadBalancer
  
# 为 ingress 专门创建一个 namespace
kubectl create ns ingress-nginx

# 为需要部署 ingress 的节点上加标签
kubectl label node k8s-master ingress=true

# 安装 ingress-nginx
helm install ingress-nginx -n ingress-nginx .

使用

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress # 资源类型为 Ingress
metadata:
  name: demo-nginx-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /  # 重写路径
spec:
  rules: # ingress 规则配置,可以配置多个
  - host: k8s.demo.cn #域名配置,可以使用通配符 *   可以配置多个host  也可以不配置host 直接通过ip:port 方式访问 配置了host 就只能通过host 不能选择ip:port 的形式
    http:
      paths: # 相当于 nginx 的 location 配置,可以配置多个 paths
    	- path: /api # 等价于 nginx 中的 location 的路径前缀匹配
      	pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配
        backend:
          service: 
            name: nginx-svc # 代理到哪个 service
            port:   # 可以直接写 80 也可以如下写法
              number: 80 # service 的端口
相关推荐
大G哥24 分钟前
记一次K8S 环境应用nginx stable-alpine 解析内部域名失败排查思路
运维·nginx·云原生·容器·kubernetes
feng_xiaoshi39 分钟前
【云原生】云原生架构的反模式
云原生·架构
妍妍的宝贝40 分钟前
k8s 中微服务之 MetailLB 搭配 ingress-nginx 实现七层负载
nginx·微服务·kubernetes
大道归简1 小时前
Docker 命令从入门到入门:从 Windows 到容器的完美类比
windows·docker·容器
爱跑步的程序员~2 小时前
Docker
docker·容器
福大大架构师每日一题2 小时前
23.1 k8s监控中标签relabel的应用和原理
java·容器·kubernetes
程序那点事儿2 小时前
k8s 之动态创建pv失败(踩坑)
云原生·容器·kubernetes
疯狂的大狗2 小时前
docker进入正在运行的容器,exit后的比较
运维·docker·容器
长天一色3 小时前
【Docker从入门到进阶】01.介绍 & 02.基础使用
运维·docker·容器
叶北辰CHINA4 小时前
nginx反向代理,负载均衡,HTTP配置简述(说人话)
linux·运维·nginx·http·云原生·https·负载均衡