k8s的service、ingress controller和ingress

我们通过deployment和statefulSet部署了多个POD了。这些POD一般会对外提供服务,比如前面的实验我们通过web这个POD提供了WEB服务。我们当然可以在集群内直接访问POD的IP来访问这些服务,但POD的IP是可能变化的,所以更标准的做法是通过service来访问POD服务。

service主要是定义POD的访问端口,可以让集群内外方便的访问POD开放的服务。它本身就相当于是一个负载均衡器,通过kube-porxy可以把访问请求路由到实际的多个POD内,实现负载均衡。

service的type有ClusterIP、ExternalName、LoadBalancer和NodePort。如果只是集群内部访问,使用ClusterIP就足够了。每个service它的ClusterIP是始终不变的,并且会自动跟踪POD的IP变化。而集群外部的访问呢更多的是借助LoadBalancer类型的service。但标准的K8S安装是没有LoadBalancer,公有云服务商有自己内部的实现,会监控LoadBalancer类型的service创建,并自动创建一个负载均衡器跟这个service关联。所以我们需要先安装一个插件用于实现这个功能。本次实验我们使用开源的metallb来实现负载均衡器功能。

LoadBalancer类型的service确实可以方便的实现集群外部的访问。但每个服务都要创建一个负载均衡器属实有些浪费了。毕竟负载均衡器是要消耗系统资源的,在公有云环境还是会产生费用的。另外负载均衡器太粗糙了,不利于根据规则,如URL匹配等进行更精细的控制。所以后面又出现了ingress和ingress controller。每个ingress controller都会创建一个LoadBalancer类型的service用于跟负载均衡器关联。而每个ingress则可描述多个service,并且复用同一个ingress controller。ingress controller会监控ingress的创建,并动态修改自己的配置以实现ingress描述的规则。所以总结下来的关系如下:负载均衡器和ingress controller是一对一的。ingress controller和ingress是一对多的,而ingress跟service也是一对多(实际上一个ingress可以描述多个服务,也可描述一个服务,不过这不重要,因为你也可以创建多个ingress)

下面的实验将从头开始一步步操作:

一、创建metallb负载均衡器

1、安装metallb负载均衡器

复制代码
curl -Lo https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml

quay.io在国内访问很慢,所以要修改一下这个文件改成在国内比较容易访问的仓库

修改metallb-native.yaml文件把:

image: quay.io/metallb/controller:v0.14.8

image: quay.io/metallb/speaker:v0.14.8

替换为:

image: quay.m.daocloud.io/metallb/controller:v0.14.8

image: quay.m.daocloud.io/metallb/speaker:v0.14.8

复制代码
TIPS:
DaoCloud 镜像加速
方法一 (推荐): 直接添加前缀 m.daocloud.io/
docker pull m.daocloud.io/quay.io/metallb/controller:v0.14.8
方法二: 替换仓库源 
docker pull quay.m.daocloud.io/metallb/controller:v0.14.8

kubectl apply -f metallb-native.yaml

2、创建metallb的配置

复制代码
more metallb-config.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: my-ip-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.23.70-192.168.1.80 # 替换为你网段内的空闲IP

我的工作节点IP为:192.168.23.44-192.168.1.45,我为负载均衡器预分配的IP地址段为:192.168.23.70-192.168.1.80。

kubectl apply -f metallb-config.yaml

这样我们metallb就安装好了,它会监控集群里面LoadBalancer类型的service创建,如果有的话就会创建一个负载均衡器(地址从192.168.23.70-192.168.1.80里面取),并跟这个service相关联。这里我们先不用创建LoadBalancer类型的service,后面安装ingress controller的时候会自动创建的。

二、安装和创建ingress controller

ingress controller有很多种,开源用的最多的应该就是nginx ingress controller。它可以用helm安装,也可以直接用yaml文件安装,如果用helm安装的话,有些镜像在国内无法下载,所以最好还是使用yaml文件安装,方便我们修改镜像。

直接下载

curl -Lo ingress-nginx4.yaml https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/cloud/deploy.yaml

修改deploy.yaml:

把registry.k8s.io/ingress-nginx/controller:v1.14.3@sha256:82917be97c0939f6ada1717bb39aa7e66c229d6cfb10dcfc8f1bd42f9efe0f81改为 registry.aliyuncs.com/google_containers/nginx-ingress-controller:v1.14.3

把registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.7@sha256:7c74a715af2c94cb734785b4d3ea1357b4f02b88e1e123c622a9cb68b62f669c改为registry.aliyuncs.com/google_containers/kube-webhook-certgen:v1.6.7

registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.7@sha256:7c74a715af2c94cb734785b4d3ea1357b4f02b88e1e123c622a9cb68b62f669c有两处,都要修改。

复制代码
kubectl apply -f ingress-nginx4.yaml

查看ingress controller的POD
kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE
ingress-nginx-controller-59cd5c7fb5-fvcvt   1/1     Running   0          39h

查看ingress controller的service
kubectl get svc -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.106.227.11    192.168.23.70   80:32131/TCP,443:30519/TCP   2d22h
ingress-nginx-controller-admission   ClusterIP      10.110.249.216   <none>          443/TCP                      2d22h

可以看到有个LoadBalancer类型的service起来了,并且关联的外部负载均衡器的IP是:192.168.23.70。这就是我们前面创建的metallb自动帮我们创建的负载均衡器。

三、创建delployment和service部署无状态业务

这个是常规操作,就不多解释了。主要是用delployment创建2个pod提供web服务,另外创建了一个service关联这2个pod。

复制代码
more deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydeploy
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - image: nginx
        name: nginx

创建的2个POD都有标签:app: web

现创建名字为nginx的service跟这个标签关联:

复制代码
more service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  type: ClusterIP
  ports:
  - name: web
    port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    app: web

kubectrl apply -f service.yaml

再确定我们的ingressclass

复制代码
kubectl get ingressclass
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       21h

可见已经在了一个名字叫nginx的 ingressclass,其对应的controller就是ingress-nginx

四、创建ingress,描述规则

可以在一个ingress部署多个service,也可以一个ingress部署一个service

复制代码
more ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    # 这里可以根据你使用的 Ingress Controller 添加特定注解
    # 例如,使用 nginx 时,可以配置重写规则等
    # nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx # 指定使用名为 "nginx" 的 IngressClass
  rules:
  - host: myapp.example.com # 域名规则
    http:
      paths:
      - path: / # 路径规则,匹配所有路径
        pathType: Prefix # 路径类型为前缀匹配
        backend: # 指定后端服务
          service:
            name: nginx # 后端 Service 的名字
            port:
              number: 80 # 后端 Service 的端口

kubectl apply -f ingress.yaml

这个ingress是基于域名的,所以HTTP请求里面一定要有host头,否则会请求失败。另外port.number是后端服务的端口,不是ingress的端口,ingress的端口是80或者443。并且好像不生效,总会按service实际的port来进行访问,而忽略这里面配置的port.number。

测试的时候需要修改hosts文件,把myapp.example.com指向192.168.23.70。访问http://myapp.example.com就相当于访问nginx服务了

再创建一个pod作为默认后端,即当请求的路径没有匹配到任何ingress规则时,就会转发到这个pod。这里的backend.service.name是nginx3,而不是nginx,并且没有配置host,所以这个ingress是默认后端。无法匹配域名或者无域名就匹配到这个规则

复制代码
more ingress_default.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: default-ingress
  annotations:
    # 这里可以根据你使用的 Ingress Controller 添加特定注解
    # 例如,使用 nginx 时,可以配置重写规则等
    # nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx # 指定使用名为 "nginx" 的 IngressClass
  rules:
  #- host: myapp.example.com # 域名规则
  - http:
      paths:
      - path: / # 路径规则,匹配所有路径
        pathType: Prefix # 路径类型为前缀匹配
        backend: # 指定后端服务
          service:
            name: nginx3 # 后端 Service 的名字
            port:
              number: 8080 # 后端 Service 的端口


kubectl apply -f ingress_default.yaml

查看当前生效的所有ingress规则

复制代码
kubectl get ingress
NAME              CLASS   HOSTS               ADDRESS         PORTS   AGE
default-ingress   nginx   *                   192.168.23.70   80      13m
example-ingress   nginx   myapp.example.com   192.168.23.70   80      72m

这时访问http://myapp.example.com就会转发到nginx服务了,而直接访问http://192.168.23.70就会转发到nginx3服务了

相关推荐
susu10830189112 小时前
Ubuntu 离线环境 安装 Docker Compose
运维·docker·容器
fengyehongWorld2 小时前
docker compose的使用
运维·docker·容器
宁波阿成4 小时前
OpenClaw Docker 完整部署与排障总文档
运维·docker·ai·容器·openclaw
小二·5 小时前
Go 语言系统编程与云原生开发实战(第34篇)
大数据·云原生·golang
智能工业品检测-奇妙智能5 小时前
docker如何进行离线部署springboot项目
spring boot·docker·容器
martin10175 小时前
Docker核心概念与实战指南
docker·容器
Zfox_6 小时前
【Docker#6】Docker 容器常用命令
linux·运维·服务器·docker·容器
石工记6 小时前
OpenClaw AI 助手 Docker Compose 一键部署文档(MacBook Pro 2020 专属版,可下载)
人工智能·docker·容器
程序员一点6 小时前
第19章:openEuler 中的容器支持(Docker 与 iSulad)
运维·docker·容器·openeuler