Kubernetes Ingress实践练习


Kubernetes Ingress-nginx 的使用

我们知道可以使用 NodePortLoadBlancer 类型的 Service 可以把应用暴露给外部用户使用,除此之外,Kubernetes 还为我们提供了一个非常重要的资源对象可以用来暴露服务给外部用户,那就是 Ingress。对于小规模的应用我们使用 NodePort 或许能够满足我们的需求,但是当你的应用越来越多的时候,你就会发现对于 NodePort 的管理就非常麻烦了,这个时候使用 Ingress 就非常方便了,可以避免管理大量的端口。

Ingress 其实就是从 Kuberenets 集群外部访问集群的一个入口,将外部的请求转发到集群内不同的 Service 上,其实就相当于 nginx、haproxy 等负载均衡代理服务器,可能你会觉得我们直接使用 nginx 就实现了,但是只使用 nginx 这种方式有很大缺陷,每次有新服务加入的时候怎么改 Nginx 配置?不可能让我们去手动更改或者滚动更新前端的 Nginx Pod 吧?那我们再加上一个服务发现的工具比如 consul 如何?貌似是可以,对吧?Ingress 实际上就是这样实现的,只是服务发现的功能自己实现了,不需要使用第三方的服务了,然后再加上一个域名规则定义,路由信息的刷新依靠 Ingress Controller 来提供。

Ingress Controller 可以理解为一个监听器,通过不断地监听 kube-apiserver,实时的感知后端 Service、Pod 的变化,当得到这些信息变化后,Ingress Controller 再结合 Ingress 的配置,更新反向代理负载均衡器,达到服务发现的作用。其实这点和服务发现工具 consul、 consul-template 非常类似。

现在可以供大家使用的 Ingress Controller 有很多,比如 traefik、nginx-controller、Kubernetes Ingress Controller for Kong、HAProxy Ingress controller,当然你也可以自己实现一个 Ingress Controller,现在普遍用得较多的是 traefik 和 nginx-controller,traefik 的性能较 nginx-controller 差,但是配置使用要简单许多,这里给大家介绍 nginx-controller 的使用。

安装 Ingress-nginx

NGINX Ingress Controller 是使用 Kubernetes Ingress 资源对象构建的,用 ConfigMap 来存储 Nginx 配置的一种 Ingress Controller 实现。

要使用 Ingress 对外暴露服务,就需要提前安装一个 Ingress Controller,我们这里就先来安装 NGINX Ingress Controller。

我们主要目的是为了测试,就使用Bare metal clusters(裸机集群)的部署方式,裸机集群方式会使用 30000-32767 范围内的端口。

部署参考资料:

# 下载资源清单文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml -O ingress.yaml

#修改镜像
vi ingress.yaml
# 将 kind: Deployment 中的 spec.template.spec.containers[0].image 的值改为如下值:
registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.0

# 执行资料清单
[root@k8s-master ingress]# kubectl apply -f ingress.yaml 
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
configmap/ingress-nginx-controller created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
service/ingress-nginx-controller-admission created
service/ingress-nginx-controller created
deployment.apps/ingress-nginx-controller created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
serviceaccount/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created

# 检查安装的结果
[root@k8s-master ingress]#  kubectl get pod,svc -n ingress-nginx
NAME                                            READY   STATUS      RESTARTS   AGE
pod/ingress-nginx-admission-create-kv747        0/1     Completed   0          7m33s
pod/ingress-nginx-admission-patch-76tx4         0/1     Completed   0          7m33s
pod/ingress-nginx-controller-65bf56f7fc-p9jbs   1/1     Running     0          7m33s

NAME                                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             NodePort    10.96.197.163   <none>        80:31688/TCP,443:31390/TCP   7m33s
service/ingress-nginx-controller-admission   ClusterIP   10.96.169.165   <none>        443/TCP                      7m33s

# 可以看到 ingress-nginx 通过 NodePort 方式帮我们暴露出来了一个http的端口31688,一个https的端口31390

# 最后别忘记把svc暴露的端口 31688,31390要放行

出现了上面的信息证明 Ingress Controller 已经安装成功。

Ingress-nginx使用

准备实验环境

安装成功后,现在我们先准备好实验环境,如下所示:ingress-demo.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-server
  template:
    metadata:
      labels:
        app: hello-server
    spec:
      containers:
      - name: hello-server
        image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server
        ports:
        - containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-demo
  name: nginx-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-demo
  template:
    metadata:
      labels:
        app: nginx-demo
    spec:
      containers:
      - image: nginx
        name: nginx
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-demo
  name: nginx-demo
spec:
  selector:
    app: nginx-demo
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello-server
  name: hello-server
spec:
  selector:
    app: hello-server
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 9000

直接创建上面的资源对象:

[root@k8s-master ingress]# kubectl apply -f ingress-demo.yaml 
deployment.apps/hello-server created
deployment.apps/nginx-demo created
service/nginx-demo created
service/hello-server created

查看创建的 deploy 和 servcie

[root@k8s-master ~]# kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
hello-server   2/2     2            2           5m11s
nginx-demo     2/2     2            2           5m11s
[root@k8s-master ~]# kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
hello-server   ClusterIP   10.96.252.210   <none>        8000/TCP   5m15s
kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP    7d20h
nginx-demo     ClusterIP   10.96.26.158    <none>        8000/TCP   5m15s

域名访问

假如我们的需求是:

请求 hello.zhangquan.me:31688把请求转发给 service-hello-server 进行处理

请求 demo.zhangquan.me:31688把请求转发给 service-nginx-demo 进行处理

资源文件如下: ingress-domain-access.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress  # 一个 ingress 相当一个转发规则
metadata:
  name: ingress-host-bar # ingress名称
spec:
  ingressClassName: nginx
  rules:
  - host: "hello.zhangquan.me"  #如果是改域名下的请求就应用下面的转发规则
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-server
            port:
              number: 8000
  - host: "demo.zhangquan.me"
    http:
      paths:
      - pathType: Prefix
        path: "/"  # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
        backend:
          service:
            name: nginx-demo  ## java,比如使用路径重写,去掉前缀nginx
            port:
              number: 8000

修改 hosts 文件让hello.zhangquan.me,demo.zhangquan.me这两个域名能够解析到我们的master节点

# hosts 文件中加入这二行
k8s-master-ip hello.zhangquan.me
k8s-master-ip demo.zhangquan.me

创建上面的资源对象:

[root@k8s-master ~]# kubectl apply -f ingress/ingress-domain-access.yaml 
ingress.networking.k8s.io/ingress-host-bar created

查看创建结果:

[root@k8s-master ~]# kubectl get ingress
NAME               CLASS   HOSTS                                  ADDRESS   PORTS   AGE
ingress-host-bar   nginx   hello.zhangquan.me,demo.zhangquan.me             80      5s

可以看到这个规则匹配了两个域名hello.zhangquan.me,demo.zhangquan.me,只要是这两个域名的请求就会按照 ingress-domain-access.yaml 文件中的规则进行处理。

访问 hello.zhangquan.me 转发到 hell-server 处理

访问 demo.zhangquan.me 转发到 nginx-demo 处理

URL Rewrite

NGINX Ingress Controller 很多高级的用法可以通过 Ingress 对象的 annotation 进行配置,比如常用的 URL Rewrite 功能,现在我们需要对访问的 URL 路径做一个 Rewrite,比如在 PATH 中添加一个 nginx 的前缀,关于 Rewrite 的操作在 ingress-nginx 官方文档中也给出对应的说明,对应的 Ingress 资源对象如下所示:ingress-url-rewrite.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress  # 一个 ingress 相当一个转发规则
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: ingress-url-rewrite # ingress名称
spec:
  ingressClassName: nginx
  rules:
  - host: "hello.zhangquan.io"  #如果是改域名下的请求就应用下面的转发规则
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-server
            port:
              number: 8000
  - host: "demo.zhangquan.io"
    http:
      paths:
      - pathType: Prefix
        path: "/nginx(/|$)(.*)"  # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
        backend:
          service:
            name: nginx-demo  ## java,比如使用路径重写,去掉前缀nginx
            port:
              number: 8000

修改 hosts 文件让hello.zhangquan.io,demo.zhangquan.io这两个域名能够解析到我们的master节点

# hosts 文件中加入这二行
k8s-master-ip hello.zhangquan.me.hello.zhangquan.io
k8s-master-ip demo.zhangquan.me,demo.zhangquan.io

创建资源对象:

[root@k8s-master ~]# kubectl apply -f ingress/ingress-url-rewrite.yaml 
ingress.networking.k8s.io/ingress-url-rewrite created

查看 ingress:

[root@k8s-master ~]# kubectl get ing
NAME                  CLASS   HOSTS                                  ADDRESS      PORTS   AGE
ingress-host-bar      nginx   hello.zhangquan.me,demo.zhangquan.me   172.31.0.4   80      47m
ingress-url-rewrite   nginx   hello.zhangquan.io,demo.zhangquan.io   172.31.0.4   80      28s

我们带上 nginx 的前缀去访问:

我们可以看到已经可以访问到页面内容了,这是因为我们在 path 中通过正则表达式 /nginx(/|$)(.*)将匹配的路径设置成了 rewrite-target 的目标路径了,所以我们访问 http://demo.zhangquan.io:31688/nginx 的时候实际上相当于访问的就是后端服务的 / 路径

Rate Limiting

我们测试下限流功能,对应的 Ingress 资源对象如下所示:ingress-limit-rate.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-limit-rate
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "1" #每秒只能放一个请求进来
spec:
  ingressClassName: nginx
  rules:
  - host: "demo.zhangquan.limitrate"
    http:
      paths:
      - pathType: Exact #精确模式,必须要访问 demo.zhangquan.limitrate 才行
        path: "/"
        backend:
          service:
            name: nginx-demo
            port:
              number: 8000

修改 hosts 文件让 haha.zhangquan.io 这个域名能够解析到我们的master节点

k8s-master-ip demo.zhangquan.limitrate

创建资源对象:

[root@k8s-master ~]# kubectl apply -f ingress/ingress-limit-rate.yaml
ingress.networking.k8s.io/ingress-limit-rate created

查看ingress:

[root@k8s-master ~]# kubectl get ing
NAME                  CLASS   HOSTS                                  ADDRESS      PORTS   AGE
ingress-host-bar      nginx   hello.zhangquan.me,demo.zhangquan.me   172.31.0.4   80      100m
ingress-limit-rate    nginx   demo.zhangquan.limitrate               172.31.0.4   80      24s
ingress-url-rewrite   nginx   hello.zhangquan.io,demo.zhangquan.io   172.31.0.4   80      54m

访问测试,快速刷新就会响应默认的 503 code

参考资料


文章作者: 张权
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 张权 !
评论
  目录