Ingress 入门

什么是ingress

通俗来讲,ingress 和Service、Deployment 都是 kubernetes 的资源类型,Ingress 用于实现用域名的方式访问K8s 内部应用。

1659680108233.jpg

Ingress 安装

首先安装 helm 管理工具:https://helm.sh/docs/intro/install/

使用 helm 安装Ingress:https://kubernetes.github.io/ingress-nginx/deploy/

1.添加 Ingress 的 helm 仓库

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

2.下载 ingress 的 helm 包至本地

helm pull ingress-nginx/ingress-nginx

3.更改对应的配置

tar xf ingress-nginx-3.6.0.tgz
cd ingress-nginx
vim values.yaml

4.需要修改的位置

  • Controller 和 admissionWebhook 的镜像地址,需要将公网镜像同步至公司内网镜像仓库。
  • hostNetwork 设置为true
  • dnsPolicy 设置为 ClusterFirstWithHostNet
  • NodeSelector 添加 ingress:“true” 部署至指定节点
  • 类型更改为kind:DaemonSet

5.部署 ingress

给需要部署ingress 的节点上打标签

$ kubectl label node k8s-master03 ingress=true
$ kubectl create ns ingress-nginx
$ helm install ingress-nginx -n ingress-nginx

Ingress 使用

一个Ingress 资源示例:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: foo.bar.com
      http:
        paths:
          - path: "/"
            pathType: Prefix
            backend:
              service:
                name: nginx-svc
                port:
                  number: 80

Ingress 需要指定 apiVersionkindmetadataspec 字段。 Ingress 对象的命名必须是合法的 DNS 子域名名称。

service 和 deployment YAML 如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: "128Mi"
              cpu: "500m"
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  ports:
    - port: 80

使用 kubectl apply -f 创建

$ kubectl apply -f nginx-ingress.yaml -f nginx-svc.yaml

http://foo.bar.com 转发到集群内的服务 nginx-svc上,完整的URL为http://nginx-svc:80/

配置 /etc/hosts 文件,如下所示:

192.168.31.217  foo.bar.com

在浏览器上访问foo.bar.com,就可以看到内容了

默认后端

没有设置规则的 Ingress 将所有流量发送到同一个默认后端,.spec.defaultBackend 则是在这种情况下处理请求的那个默认后端。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-resource-backend
spec:
  defaultBackend:
    resource:
      apiGroup: k8s.example.com
      kind: StorageBucket
      name: static-assets
  rules:
    - http:
        paths:
          - path: /icons
            pathType: ImplementationSpecific
            backend:
              resource:
                apiGroup: k8s.example.com
                kind: StorageBucket
                name: icon-assets

路径类型

Ingress 中的每个路径都需要有对应的路径类型(Path Type)。未明确设置 pathType 的路径无法通过合法性检查。当前支持的路径类型有三种:

  • ImplementationSpecific:对于这种路径类型,匹配方法取决于 IngressClass。 具体实现可以将其作为单独的 pathType 处理或者与 Prefix 或 Exact 类型作相同处理。

  • Exact:精确匹配 URL 路径,且区分大小写。

  • Prefix:基于以 / 分隔的 URL 路径前缀匹配。匹配区分大小写,并且对路径中的元素逐个完成。 路径元素指的是由 / 分隔符分隔的路径中的标签列表。

类型 路径 请求路径 匹配与否?
Prefix / (所有路径)
Exact /foo /foo
Exact /foo /bar
Exact /foo /foo/
Exact /foo/ /foo
Prefix /foo /foo, /foo/
Prefix /foo/ /foo, /foo/
Prefix /aaa/bb /aaa/bbb
Prefix /aaa/bbb /aaa/bbb
Prefix /aaa/bbb/ /aaa/bbb 是,忽略尾部斜线
Prefix /aaa/bbb /aaa/bbb/ 是,匹配尾部斜线
Prefix /aaa/bbb /aaa/bbb/ccc 是,匹配子路径
Prefix /aaa/bbb /aaa/bbbxyz 否,字符串前缀不匹配
Prefix /, /aaa /aaa/ccc 是,匹配 /aaa 前缀
Prefix /, /aaa, /aaa/bbb /aaa/bbb 是,匹配 /aaa/bbb 前缀
Prefix /, /aaa, /aaa/bbb /ccc 是,匹配 / 前缀
Prefix /aaa /ccc 否,使用默认后端
混合 /foo (Prefix), /foo (Exact) /foo 是,优选 Exact 类型

主机名通配符

主机名可以是精确匹配(例如 foo.bar.com),也可以使用通配符匹配(例如 *.bar.com)。精确匹配要求 HTTP host 头部字段与 host 字段一致,通配符匹配要求 HTTP host 头部字段与通配符规则中的后缀部分相同。

主机 host 头部 匹配与否?
*.foo.com bar.foo.com 基于相同的后缀匹配
*.foo.com baz.bar.foo.com 不匹配,通配符仅覆盖了一个 DNS 标签
*.foo.com foo.com 不匹配,通配符仅覆盖了一个 DNS 标签

将同一域名的不同 URL 路径转发到不同的服务(Simple Fanout)

根据请求的 HTTP URI 将来自同一 IP 地址的流量路由到多个 Service。

1659681615852.jpg

Ingress 配置如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-fanout-example
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 4200
      - path: /bar
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 8080

使用 kubectl apply -f 创建 Ingress

$ kubectl apply -f ingress.yaml

查看 Ingress 详细信息

$ kubectl describe ingress simple-fanout-example
Name:             simple-fanout-example
Namespace:        default
Address:          178.91.123.132
Default backend:  default-http-backend:80 (10.8.2.3:8080)
Rules:
  Host         Path  Backends
  ----         ----  --------
  foo.bar.com
               /foo   service1:4200 (10.8.0.90:4200)
               /bar   service2:8080 (10.8.0.91:8080)
Annotations:
  nginx.ingress.kubernetes.io/rewrite-target:  /
Events:
  Type     Reason  Age                From                     Message
  ----     ------  ----               ----                     -------
  Normal   ADD     22s                loadbalancer-controller  default/test

将不同的域名转发到不同的服务

基于名称的虚拟主机支持将针对多个主机名的 HTTP 流量路由到同一 IP 地址上。

1659682444066.jpg
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service1
            port:
              number: 80
  - host: bar.foo.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service2
            port:
              number: 80

HTTPS 配置

通过设定包含 TLS 私钥和证书的 Secret 来保护 Ingress。 Ingress 只支持单个 TLS 端口 443。 TLS Secret 的数据中必须包含用于 TLS 的以键名 tls.crt 保存的证书和以键名 tls.key 保存的私钥。

apiVersion: v1
kind: Secret
metadata:
  name: testsecret-tls
  namespace: default
data:
  tls.crt: base64 编码的证书
  tls.key: base64 编码的私钥
type: kubernetes.io/tls
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

更新 Ingress

可以使用 kubectl edit 更新 Ingress ,也可以使用 kubectl replace -f 更新 ingress.yaml 文件。

推荐阅读更多精彩内容