K8S_基础设施_Ingress服务暴露


目录:

K8S服务暴露介绍

首先简要了解一下K8S中提供的暴露服务的三种方式

  1. LoadBlancer

该方式是kubernetes深度结合云平台的一个组件。当集群运行在云厂商提供的云平台上时,常用该方式对外暴露服务(收费)。

  1. NodePort

通过在集群的每个NodePort上暴露端口,访问指定端口即可访问到指定服务。一般使用这种方式时,都是选择固定端口,但服务一多就容易产生冲突或者不方便管理的情况。

  1. Ingress(方式)

  2. Ingress Controller

    Ingress Controller 实质上可以理解为是个监视器,Ingress Controller 通过不断地跟 kubernetes API 打交道,实时的感知后端 service、pod 等变化,比如新增和减少 pod,service 增加与减少等;当得到这些变化信息后,Ingress Controller 再结合下文的 Ingress 生成配置,然后更新反向代理负载均衡器,并刷新其配置,达到服务发现的作用

  3. Ingress(资源清单)

    Ingress 简单理解就是个规则定义;比如说某个域名对应某个 service,即当某个域名的请求进来时转发给某个 service;这个规则将与 Ingress Controller 结合,然后 Ingress Controller 将其动态写入到负载均衡器配置中,从而实现整体的服务发现和负载均衡

服务访问流程图如下(具体查看官方文档,本文底下有链接):

使用

安装步骤大概分为以下:

  1. 安装Ingress Controller Pod
  2. 部署服务并对外暴露
  3. 部署ingress

安装Ingress Controller Pod

注意:

  1. 国内无法下载官方Ingress Controller部署文件,且无法通过helm进行下载,所以下载三方部署文件。

  2. 其次容器镜像也无法下载,需要使用三方镜像源。

  3. 默认下载的deploy部署文件是LoadBlancer进行服务暴露(需要云厂商支持),所以需要更改配置文件使用NodePort方式。

下载deploy文件

# 下载对应的yml
$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/cloud/deploy.yaml
# 替换镜像地址(国内无法下载)
$ sed -i 's@k8s.gcr.io/ingress-nginx/controller:v1.1.1\(.*\)@duangx/ingress-nginx-controller:v1.1.@' deploy.yaml
$ sed -i 's@k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1\(.*\)$@duangx/kube-webhook-certgen:v1.1.1@' deploy.yaml
# 修改yml文件名
$ mv deploy.yaml  ingress-nginx.yaml

修改deploy文件

配置ingress controller以NodePort的形式暴露,使其能通过域名+端口访问,再通过指定后缀名的方式访问到具体服务。例如http://test.wlhiot.com:30080/test,访问http://test.wlhiot.com:30080其实是访问ingress controller。

$ vim ingress-nginx.yaml  # 搜索LoadBalancer的资源清单,将其注释。替换成NodePort
apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    helm.sh/chart: ingress-nginx-4.0.15
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 1.1.1
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
      appProtocol: http
      nodePort: 30080
    - name: https
      port: 443
      protocol: TCP
      targetPort: https
      appProtocol: https
      nodePort: 30443
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/component: controller

部署

$ kubectl apply -f ingress-nginx.yaml  # 运行过程中出现报错可查看是否是因为镜像问题造成
$ kubectl get all -n ingress-nginx  # 查看部署情况
NAME                                            READY   STATUS      RESTARTS   AGE
pod/ingress-nginx-admission-create--1-v4hbn     0/1     Completed   0          18h
pod/ingress-nginx-admission-patch--1-xkxbz      0/1     Completed   2          18h
pod/ingress-nginx-controller-69d84f9c5f-dl28r   1/1     Running     0          18h

NAME                                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             NodePort    10.254.21.242   <none>        80:30080/TCP,443:30443/TCP   18h
service/ingress-nginx-controller-admission   ClusterIP   10.254.202.85   <none>        443/TCP                      18h

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           18h

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-nginx-controller-69d84f9c5f   1         1         1       18h

NAME                                       COMPLETIONS   DURATION   AGE
job.batch/ingress-nginx-admission-create   1/1           17s        18h
job.batch/ingress-nginx-admission-patch    1/1           34s        18h
$ kubectl delete -f ingress-nginx.yaml  # 卸载

使用NGINX测试

$ kubectl create ns test  # 创建命名空间
$ kubectl create deployment  test-ingress --image=nginx -n test  # 在test命名空间创建nginx
$ kubectl expose deployment test-ingress --port=80 --target-port=80 --type=NodePort  -n test  # 暴漏端口
$ kubectl apply -f test-ingress.yml
$ kubectl get pod -o wide -n test
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
test-ingress-5c4bb6ff8-t4ml5   1/1     Running   0          21h   10.20.7.215   k8s-node07   <none>           <none>
$ kubectl exec -it -n test test-ingress-5c4bb6ff8-t4ml5 -- /bin/bash
root@test-ingress-5c4bb6ff8-t4ml5:/# echo "test-nginx" >  /usr/share/nginx/html/index.html
$ kubectl get svc -o wide -n test
NAME           TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE   SELECTOR
test-ingress   NodePort   10.254.147.162   <none>        80:32117/TCP   21h   app=test-ingress
$ curl 192.168.254.23:32117  # 192.168.254.23为master地址
test-nginx

修改本地解析

解析这块有点知识点,虽然test.wlhiot.com在公网上确实是有这么一个域名且能访问。但是DNS的解析顺序是先从本地查找,若查找不到再通过域名服务器/etc/resolv.conf进行查找。

所以当在本机添加test.wlhiot.com的条目后,再通过该域名访问它优先解析成192.168.254.23。

关于DNS解析可查看http://www.dhr2333.cn/article/2022/7/1/38.html

C:\Windows\System32\drivers\etc/hosts  # Windows,因为我是在windows中进行访问服务
/etc/hosts  # Linux
192.168.254.23 ebox.test.wlhiot.com  # [master的IP地址] [自定义域名]

部署Ingress

$ vim test-ingress.yml  # 创建ingress服务
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-service
  namespace: test
spec:
  ingressClassName: nginx   
  rules:
  - host: ebox.test.wlhiot.com  # 自定义域名
    http:
      paths:
      - pathType: Prefix
        path: /  # 后缀
        backend:
          service:
            name: test-ingress  # 上面创建的服务名 svc
            port:
              number: 80
$ curl ebox.test.wlhiot.com:30080  # [自定义域名]:[ingress-controller的NodePort]/[后缀]

实现效果

参考资料: