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服务了

相关推荐
正经教主41 分钟前
【docker基础】 第七课:Docker Compose 多容器实战
运维·docker·容器
正经教主1 小时前
【docker基础】Redis的docker部署
redis·docker·容器
DolphinScheduler社区1 小时前
Apache DolphinScheduler 3.4.2 正式发布!新增 Amazon EMR Serverless 插件,增强监控与补数据能力
大数据·云原生·serverless·apache·海豚调度·版本发版
成为你的宁宁1 小时前
【基于 Prometheus Operator 实现 K8s 环境下 Redis Cluster 集群监控部署】
redis·kubernetes·prometheus
是一个Bug2 小时前
Docker 与 Kubernetes:从“集装箱”到“远洋舰队”
docker·容器·kubernetes
heimeiyingwang2 小时前
【架构实战】注册中心选型:Nacos vs Eureka vs Consul
微服务·云原生·架构
java_cj2 小时前
阅读 k8s 源码的准备工作
云原生·容器·kubernetes
开发者联盟league2 小时前
使用Jenkins整合Sonarqube/Gitlab/Harbor/Kubernetes实现CICD
kubernetes·gitlab·jenkins
蜀道山老天师2 小时前
OpenClaw 从零部署 + 飞书机器人完整接入(实操篇)
运维·docker·容器·飞书
robinLi09132 小时前
docker mac 下载不同系统架构镜像
macos·docker·容器