IT 铁人赛 k8s 入门30天 -- day10 K8s Ingress explained

前言

今天将会讲解 Ingress 这个元件

包括用途, 用法还有实际案例

什麽是 Ingress

假设我们布署了一个 my-app 的 Pod

当想要透过浏览器去存去这个 my-app

有一个作法是建立一个 my-app 的外部 Service

这样一来就可以透过 Service 的外部 IP 加上对外开放服务的 Port 来存取 my-app

但这种作法其实很不方便 因为必须去找到 Service 的外部 IP

这时候就会需要 Ingress 这个元件来提供域名服务

让使用者透过域名来存取 my-app 如下图:

External Service vs Ingress 设定档

External Service

apiVersion: v1
kind: Service
metadata:
  name: myapp-external-service
spec:
 selector:
   app: myapp
 type: LoadBalancer
 ports:
   - protocol: TCP
     port: 8080
     targetPort: 8080
     nodePort: 35010

External Service 的类型是 LoadBalancer
代表会给予一个对外的 IP

指定的 nodePort 是给外部存取 Service 的接口

Ingress

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: myapp-ingress
spec:
  rules:
  - host: myapp.com
    http:
      paths:
      - backend:
         serviceName: myapp-internal-service
         servicePort: 8080

Ingress 的类型是 Ingress

spec 的 rules 是设定路由规则

以这边的例子规则是所有域名是 myapp.com 的封包都 forward 到 myapp-internal-service:8080

paths 这边就是设定 url

注意的是, 这里的 http 指的是 myapp-internal-service 所服务的 protocol 而不是外部的 protocol

而对应的 Internal Service 如下:

apiVersion: v1
kind: Service
metadata:
  name: myapp-internal-service
spec:
  selector:
    app: myapp
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

host 需要是一个合法的域名

host 用来把外部域名, 对应到 Node IP Address

Ingress Controller

除了刚刚设定之外

Ingress 发布需要一个 Ingress 实作实体, 也就是所谓 Ingress Controller

Ingress Controller 是实际在执行路由的实体, 会根据 Ingress 的 rules 来直接封包路由

架构图如下:

Ingress Controller 的实作有很多第三方套件可以用

k8s 官方提供可用的 Ingress Controller 选项

而实际布署要选用哪种 Ingress Controller 要根据 k8s 丛集建制环境来决定

假设是建立在云服务商上面的话

可能就有云服务商提供的选项, 所谓 cloud load balancer

而使用云服务商提供的 cloud load balancer, 举例来说: AWS 的 ELB

好处就是不必自行去实现负载平衡的功能

架构如下:

但如果是没有用云服务商, 而是像是使用 minikube 这类 local run 的丛集的话

就要自行架设 load balancer, 可以是在丛集之内或是之外的服务器

安全一点的作法一台服务器当 proxy 转发封包到 Ingress Controller

这样对外的接口就只有那台 proxy server, 而 k8s cluster 就不需有对外的接口

架构图如下:

在 minikube 安装 Ingress Controller

minikube addons enable ingress

这个设定是自动启用了 k8s Nginx 的 Ingress Controller

这个设定也可以用在 production 环境

当 ingress 被 enabled 之後可以查询 namespace 是 ingress-nginx 的 Pod

把 kubernetes-dashboard 改用 ingress 方式呈献

执行以下指令

minikube dashboard

之後就可以透过 localhsot 察看 minikube 的 status

会发现多了一个 namespace 叫作 kubernete-dashboard

查询这个 namespace 下面的 Pod

会发现 kubernetes-dashboard 这个 Service 没有对外开放

所以需要使用 Ingress 建立路由才存取

目标建立 hostname 为 dashboard.com 来存取 kuberenetes-dashboard 这个 Service 内容

建立 dashboard-ingress.yaml 如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: dashboard-ingress
  namespace: kubernetes-dashboard
spec:
  rules:
  - host: dashboard.com
    http:
      paths:
      - pathType: ImplementationSpecific
        backend:
          service:
            name: kubernetes-dashboard
            port:
              number: 80

语法参考自k8s 官方文件

关键点:

1 设定 host 为 dashboard.com(你想要设定域名)

2 设定 service 的 name 还有 port 到要连结的 Service

举例来说: 这边的 name 设定是 kubernetes-dashboard, port 是 80

因为前面 kubectl get pod -n kuberenetes-dashboard 结果

3 设定 metadata 内, 对应的 namespace 为 kuberenetes-dashboard

因为这是属於 kuberenetes-dashboard 类别所有放在这个 namespace

另外因为这样放 可以让 service 的 name url 的比较简单, 如果放在不同 namespace 则必须要指定 kuberenetes-dashboard Service 的 namespace

4 kind 是 Ingress 类别

5 pathType 是 ImplementationSpecific, 这里类别有三种 Exact, Prefix, ImplementationSpecific. Exact 代表 path 要完全一样才进入路由, Prefix 代表只要前置有包换就进入路由, ImplementationSpecific 代表根据 IngressClass 来决定

6 Ingress Class 是由 Ingress Controller 所提供的选项

每个 Ingress Controller 会实作自己的比对模式并对应到一种 Ingress Class

所以这边的 Ingress Class 要去查询 Ingress Controller 所提供的类别

使用以下指令, 发布 Ingress

kubectl apply -f dashboard-ingress.yaml

检查 ingress

这时候如果直接 到浏览器

http://dashboard.com 输入

就会发现

原因是因为我们只设定好路由

但是没做域名转换

因此在本机电脑这边需要 在 /etc/hosts 内 加入下面一行

192.168.49.2 dashboard.com

注意的是 这边前面的 192.168.49.2 是从

kubectl get ingress -n kubernetes-dashboard 

拿到的 IP 随着每个人电脑不同会有不同的结果

修改完 /etc/hosts 存档之後

重新再浏览器输入 http://dashboard.com

dashboard default-backend

透过以下指令

kubectl describe ingress dashboard-ingress -n kubernetes-dashboard

会发现有一个 Default backend 的栏位

而这个是 Ingress 用来处理没被原本 Service 定义路由的 request

但这边可以看到还没有给予任何 Service 来处理

所以再处理 request 时 假设遇到没有被 forward 过去的 Service 处理到的路由

就会跳出一些 404 网页找不到 等等预设错误

而不是客制化的错误页面

想要建立一个客制化页面

来处理此问题的方式就是建立一个 Internal Service 对应到这个 default-http-backend

在这个 Internal Service去实作客制化的页面

建立 default-http-backend.yaml 如下

apiVersion: v1
kind: Service
metadata:
  name: default-http-backend
spec:
  selector:
    app: default-response-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

由於处理方式很多, 在此就不做更深入实作

多个路由路径的 Ingress

除了刚刚那个直接对应的 Service 的路由

Ingress 也支援多个路由对应的方式

举例如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-fanout-example
spec:
  rules:
  - host: myapp.com
    http:
      paths:
      - path: "/analytics"
        path: Prefix
        backend:
          service:
            name: analytics-service
            port:
              number: 3000
      - path: "/shopping"
        pathType: Exact
        backend:
          service:
            name: shopping-service
            port:
              number: 8080

就可以做到以下的路由

多个子域名的 Ingress

Ingress 也支援多个子域名对应的方式

举例如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: name-virtual-host-ingress-no-third-host
spec:
  rules:
  - host: analytics.myapp.com
    http:
      paths:
      - path: "/"
        path: Prefix
        backend:
          service:
            name: analytics-service
            port:
              number: 3000
  - host: shopping.myapp.com
    http:
      - path: "/"
        pathType: Exact
        backend:
          service:
            name: shopping-service
            port:
              number: 8080

就可以做到以下的路由

TLS 设定

要建立 TLS 必须要先建立 certificate 跟 key pair

然後把 certificate 跟 private 放在 Secret 内

建立 sample-tls-secret.yaml 如下:

apiVersion: v1
kind: Secret
metadata:
  name: testsecret-tls
  namespace: default
data:
  tls.crt: base64 encoded cert
  tls.key: base64 encoded key
type: kubernetes.io/tls

然後在 Ingress 设定内取用这个 Secret 在 tls 设定的部份

建立 tls-example-ingress.yaml 如下

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-example-ingress
spec:
  tls:
  - hosts:
      - https-example.foo.com
    secretName: testsecret-tls
  rules:
  - host: https-example.foo.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80

关键点:

1 tls 设定的 hosts 一定要跟 rules 内指令的 host 一样

2 这个范例是根据nginx的规则所写, 不同的 Ingress Controller 可能会有不同的 tls 设定

3 secretName 对应到刚刚 TLS 建立的 Secret 名称

4 Secret 与 Ingress 必须建立在同一个 Namespace


<<:  Day09: 【TypeScript 学起来】物件型别 Object Types : Arrays / Function

>>:  Day 11:合并排序(mergesort)

CSS 命名基础介绍 DAY40

今天要来介绍 CSS 命名 首先先来介绍 驼峰式命名: https://zh.wikipedia.o...

Day25 React Router useParams

我们可以在一般的静态URL网址上加上动态路由参数,在 URL 中设置动态参数允许路由在将 URL ...

IT 铁人赛 k8s 入门30天 -- day1 什麽是k8s? k8s能做到什麽?

前言 身为一位 常常在使用容器的开发者 对於容器的管理是一件很重要的事情 特别是在大量使用容器的时候...

javascript网页座标(screen,page,client)

下面三种座标的(x,y)都是从左上角开始为(0,0) screen 根据整个萤幕的宽高 page 根...

Day03 - 安装 Laradock 环境建置

闲话家常 用Laravel开发系统,那就用Laradock架设环境吧! 首先到 Laradock 下...