18-1、k8s 对外服务之ingress

一、什么是ingress

原来的项目是部署在一台电脑上的,这样爬取速度虽然很快,但是我们还能提升,联想到分布式的思想,我们是否可以通过多台电脑进行配合爬取,这样我们的爬取速度就能大幅度提升。                              
k8s对外暴露服务service的主要方式是NodePort与LoadBalance,但是随着集群中微服务的增多,NodePort方式缺点是会占用很多集群机器的端口,
LoadBalance方式最大的缺点是每个service一个LB,有点浪费和麻烦,而且需要k8s的支持。
ingress则只需要一个NodePort或者一个LoadBalance就可以满足所有service对外服务的需求,所以通常情况下 我们会设计一个Ingress来做路由的转发,方便统一管理。效果如图:      

18-1、k8s 对外服务之ingress_第1张图片

 实际上,ingress相当于一个7层的负载均衡器,是k8s对反向代理的抽象,工作原理类似于nginx,可以理解为在Ingress里建立一个映射规则, ingress controller通过监听Ingress这个api对象里的配置规则并转化成nginx的配置,然后对外部提供服务。

1.1、Ingress组成

主要分为两部分:
    Ingresscontroller:是流量的入口,核心是一个deployment,封装了一个web前端负载均衡器,同时在其基础上实现动态感知Ingress并根据Ingress的定义动态生成前端web负载均衡器的配置文件,比如 Nginx Ingress Controller 本质上就是一个 Nginx,只不过它能根据 Ingress 资源的定义动态生成 Nginx 的配置文件,然后动态 Reload。   实现方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,需要编写的yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的类型可以是NodePort或者LoadBalancer。
  ingress resourcesIngress描述具体的路由规则,一个类型为Ingress的k8s api对象,这部分则是面向开发人员。该资源对象定义了不同主机名(域名)及URL和对应后端Service的绑定,根据不同的路径路由http和https流量。
 Ingress Controller是将Ingress这种变化生成一段Nginx的配置,然后将这个配置通过Kubernetes API写到Nginx的Pod中,然后reload。
(注意:写入 nginx.conf 的不是service的地址,而是service backend 的 pod 的地址,避免在 service 再增加一层负载均衡转发)

18-1、k8s 对外服务之ingress_第2张图片

    从上图看出,实际上请求进来还是被负载均衡器拦截了,比如nginx,然后ingress controller通过跟ingress交互得知某个域名对应哪个service, 再通过跟kubernetes API交互得知service地址等信息,综合以后生成配置文件实时写入负载均衡器(nginx),然后负载均衡器reload该规则便可实现服务发现,即动态映射。

1.2、Ingress作用

  1. 基于http-header的路由
  2. 基于path的路由
  3. 单个ingress的timeout
  4. 请求速率limit
  5. rewrite规则
Ingress 可以提供负载平衡、SSL终止 和 基于名称的虚拟主机。
当然在实际应用中,最新版本 Kubernetes 已经将 Nginx 与 Ingress Controller 合并为一个组件,所以 Nginx 无需单独部署, 只需要部署 Ingress Controller 即可。

二、helm 裸机部署 Nginx Ingress Controller   

基于 Nginx 的 Ingress Controller 有两种,一种是 k8s 社区提供的  ingress-nginx ,另一种是 Nginx 社区提供的  kubernetes-igress ,关于两者的区别见  这里
yaml文件中的镜像不能下载可以换其他的image:
nginx-ingress.yaml:
apiVersion: v1
kind: Namespace
metadata:
  labels:
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  name: ingress-nginx
---
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx
  namespace: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-admission
  namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx
  namespace: ingress-nginx
rules:
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - configmaps
  - pods
  - secrets
  - endpoints
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - services
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses/status
  verbs:
  - update
- apiGroups:
  - networking.k8s.io
  resources:
  - ingressclasses
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resourceNames:
  - ingress-controller-leader
  resources:
  - configmaps
  verbs:
  - get
  - update
- apiGroups:
  - ""
  resources:
  - configmaps
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-admission
  namespace: ingress-nginx
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
  - create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx
rules:
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - nodes
  - pods
  - secrets
  - namespaces
  verbs:
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - services
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses/status
  verbs:
  - update
- apiGroups:
  - networking.k8s.io
  resources:
  - ingressclasses
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-admission
rules:
- apiGroups:
  - admissionregistration.k8s.io
  resources:
  - validatingwebhookconfigurations
  verbs:
  - get
  - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx
  namespace: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: ingress-nginx
subjects:
- kind: ServiceAccount
  name: ingress-nginx
  namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-admission
  namespace: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
  name: ingress-nginx-admission
  namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: ingress-nginx
subjects:
- kind: ServiceAccount
  name: ingress-nginx
  namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-admission
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
  name: ingress-nginx-admission
  namespace: ingress-nginx
---
apiVersion: v1
data:
  allow-snippet-annotations: "true"
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-controller
  namespace: ingress-nginx
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  ports:
  - appProtocol: http
    name: http
    port: 80
    protocol: TCP
    targetPort: http
  - appProtocol: https
    name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: NodePort
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-controller-admission
  namespace: ingress-nginx
spec:
  ports:
  - appProtocol: https
    name: https-webhook
    port: 443
    targetPort: webhook
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  minReadySeconds: 0
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/component: controller
      app.kubernetes.io/instance: ingress-nginx
      app.kubernetes.io/name: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/component: controller
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/name: ingress-nginx
    spec:
      containers:
      - args:
        - /nginx-ingress-controller
        - --election-id=ingress-controller-leader
        - --controller-class=k8s.io/ingress-nginx
        - --ingress-class=nginx
        - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
        - --validating-webhook=:8443
        - --validating-webhook-certificate=/usr/local/certificates/cert
        - --validating-webhook-key=/usr/local/certificates/key
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: LD_PRELOAD
          value: /usr/local/lib/libmimalloc.so
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.1.1
        imagePullPolicy: IfNotPresent
        lifecycle:
          preStop:
            exec:
              command:
              - /wait-shutdown
        livenessProbe:
          failureThreshold: 5
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        name: controller
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
        - containerPort: 443
          name: https
          protocol: TCP
        - containerPort: 8443
          name: webhook
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources:
          requests:
            cpu: 100m
            memory: 90Mi
        securityContext:
          allowPrivilegeEscalation: true
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - ALL
          runAsUser: 101
        volumeMounts:
        - mountPath: /usr/local/certificates/
          name: webhook-cert
          readOnly: true
      dnsPolicy: ClusterFirst
      nodeSelector:
        kubernetes.io/os: linux
      serviceAccountName: ingress-nginx
      terminationGracePeriodSeconds: 300
      volumes:
      - name: webhook-cert
        secret:
          secretName: ingress-nginx-admission
---
apiVersion: batch/v1
kind: Job
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-admission-create
  namespace: ingress-nginx
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/component: admission-webhook
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
        app.kubernetes.io/version: 1.2.0
      name: ingress-nginx-admission-create
    spec:
      containers:
      - args:
        - create
        - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
        - --namespace=$(POD_NAMESPACE)
        - --secret-name=ingress-nginx-admission
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1
        imagePullPolicy: IfNotPresent
        name: create
        securityContext:
          allowPrivilegeEscalation: false
      nodeSelector:
        kubernetes.io/os: linux
      restartPolicy: OnFailure
      securityContext:
        fsGroup: 2000
        runAsNonRoot: true
        runAsUser: 2000
      serviceAccountName: ingress-nginx-admission
---
apiVersion: batch/v1
kind: Job
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-admission-patch
  namespace: ingress-nginx
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/component: admission-webhook
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
        app.kubernetes.io/version: 1.2.0
      name: ingress-nginx-admission-patch
    spec:
      containers:
      - args:
        - patch
        - --webhook-name=ingress-nginx-admission
        - --namespace=$(POD_NAMESPACE)
        - --patch-mutating=false
        - --secret-name=ingress-nginx-admission
        - --patch-failure-policy=Fail
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1
        imagePullPolicy: IfNotPresent
        name: patch
        securityContext:
          allowPrivilegeEscalation: false
      nodeSelector:
        kubernetes.io/os: linux
      restartPolicy: OnFailure
      securityContext:
        fsGroup: 2000
        runAsNonRoot: true
        runAsUser: 2000
      serviceAccountName: ingress-nginx-admission
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: nginx
spec:
  controller: k8s.io/ingress-nginx
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.2.0
  name: ingress-nginx-admission
webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    service:
      name: ingress-nginx-controller-admission
      namespace: ingress-nginx
      path: /networking/v1/ingresses
  failurePolicy: Fail
  matchPolicy: Equivalent
  name: validate.nginx.ingress.kubernetes.io
  rules:
  - apiGroups:
    - networking.k8s.io
    apiVersions:
    - v1
    operations:
    - CREATE
    - UPDATE
    resources:
    - ingresses
  sideEffects: None
执行命令kubectl apply -f nginx-ingress.yaml

查看:kubectl get pods -n ingress-nginx -o wide:

三、Ingress resource

一个最小的Ingress资源示例:service/networking/minimal-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx-example
  rules:
  - http:
      paths:
      - path: /testpath
        pathType: Prefix
        backend:
          service:
            name: test
            port:
              number: 80
1、Ingress需要apiVersion、kind、metadata字段;
2、Ingress对象的名称必须是有效的 DNS subdomain name .
  18-1、k8s 对外服务之ingress_第3张图片
3、Ingress spec包含配置负载均衡器 或 代理服务器所需的所有信息,最重要的是它包含与所有传入请求匹配的规则列表。Ingress resource仅支持引导HTTP(S)流量的规则。
4、 Ingress rules:
    每个HTTP规则都包含以下信息:
  • host:可选主机,在此示例中,未指定主机,因此该规则适用于通过指定 IP 地址的所有入站 HTTP 流量。 如果提供了主机(例如 foo.bar.com),则规则适用于该主机。
  • paths列表(例如 /testpath),每个路径都有一个关联的 backend,该后端使用  service.name 和  service.port.name 或  service.port.number 定义。 在负载均衡器将流量定向到引用的服务之前,host和path都必须匹配传入请求的内容。
  • backend是Service文档中描述的服务和端口名称的组合,或者是通过 CRD 的自定义资源后端。 对与规则的主机和路径匹配的 Ingress 的 HTTP(和 HTTPS)请求将发送到列出的后端。
defaultBackend通常在 Ingress controller中配置,以服务与规范中的路径不匹配的任何请求。

3.1、DefaultBackend

没有rules的 Ingress 将所有流量发送到单个默认后端。 defaultBackend 通常是   Ingress controller 的配置选项,并且未在 Ingress resource中指定。
如果没有任何主机或路径与 Ingress 对象中的 HTTP 请求匹配,则流量将路由到您的默认后端。
使用 kubectl get service -n kube-system查看在命名空间 kube-system 是否有 default-back-end 服务。
若没有,使用下面的 yaml 文件 创建 default-back-end 服务
backend.yaml:
apiVersion: v1
kind: Service
metadata:
  name: default-http-backend
  namespace: kube-system
spec:
  selector:
    app: ingress-nginx-controller
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

3.2、Resource backends

资源后端是与 Ingress 对象位于同一命名空间中的另一个 Kubernetes 资源的 ObjectRef。service/networking/ingress-resource-backend.yaml:
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后,使用 kubectl describe ingress ingress-resource-backend查看:
​
Name: ingress-resource-backend
Namespace: default
Address:
Default backend: APIGroup: k8s.example.com, Kind: StorageBucket, Name: static-assets
Rules:
Host Path Backends
---- ---- --------
*
/icons APIGroup: k8s.example.com, Kind: StorageBucket, Name: icon-assets
Annotations: 
Events: 

3.3、Path types

Ingress中的每条path都需要相应的 pathType,不包含显示 pathType的路径将无法通过验证。
支持三种路径类型:
  • ImplementationSpecific 使用这种路径类型,匹配取决于 IngressClass。 实现可以将其视为单独的 pathType 或将其视为 Prefix 或 Exact 路径类型。
  • Exact 精确匹配 URL 路径并区分大小写。
  • Prefix 基于由 / 分隔的 URL 路径 前缀进行匹配 。 匹配区分大小写 ,并在逐个元素的路径元素基础上完成。 路径元素是指由 / 分隔符分割的路径中的标签列表。 如果每个 p 都是请求路径的 p 的元素前缀,则请求是路径 p 的匹配项。
18-1、k8s 对外服务之ingress_第4张图片
在某些情况下,一个 Ingress 中的多个路径paths将匹配一个请求。 在这些情况下,将 优先考虑最长的匹配路径 。 如果两条路径仍然相等匹配,则具有 精确路径类型的路径将优先于前缀路径类型。

3.4、Hostname wildcards(主机名通配符)

Host可以是精确匹配(例如“ foo.bar.com”)或通配符(例如“ *. foo.com”)。 精确匹配要求 HTTP 主机标头与主机字段匹配。 通配符匹配要求 HTTP 主机标头等于通配符规则的后缀。
18-1、k8s 对外服务之ingress_第5张图片
service/networking/ingress-wildcard-host.yaml:
​
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-wildcard-host
spec:
  rules:
  - host: "foo.bar.com"
    http:
      paths:
      - pathType: Prefix # 前缀匹配
        path: "/bar"
        backend:
          service:
            name: service1
            port:
              number: 80
  - host: "*.foo.com" # 主机名通配符
    http:
      paths:
      - pathType: Prefix
        path: "/foo"
        backend:
          service:
            name: service2
            port:
              number: 80

3.5、Ingress class

Ingresses可由不同的controllers实现 通常具有不同的配置。每个 Ingress 都应该指定一个类,一个对 IngressClass 资源的引用,该资源包含额外的配置,包括应该实现该类的控制器的名称。
service/networking/external-lb.yaml:
​
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: external-lb
spec:
  controller: example.com/ingress-controller # 要使用的具体参数类型取决于您在 IngressClass 的 .spec.controller 字段中指定的入口控制器
  parameters:
    apiGroup: k8s.example.com
    kind: IngressParameters
    name: external-lb

四、Type of Ingress

4.1、Ingress backed by a single Service

现有的 Kubernetes 概念允许您公开单个服务(请参阅替代方案 alternatives)。 您也可以通过指定没有规则的默认后端来使用 Ingress 执行此操作。
service/networking/test-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
spec:
  defaultBackend:
    service:
      name: test
      port:
        number: 80
kubectl apply -f后查看Ingress的状态  kubectl get ingress test-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress external-lb * 203.0.113.123 80 59s
其中 203.0.113.123 是 Ingress controller为满足这个 Ingress 而分配的 IP。

4.2、Simple fanout

根据请求的HTTP URI将流量从单个IP地址路由到多个服务。Ingress允许你将负载均衡器的数量降至最低。
18-1、k8s 对外服务之ingress_第6张图片
上图中的设置将需要如下的Ingress:
service/networking/simple-fanout-example.yaml:
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 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)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test

4.3、Name based virtual hosting(基于名称的虚拟主机)

基于名称的虚拟主机支持 将 HTTP 流量路由到同一 IP 地址的多个主机名
18-1、k8s 对外服务之ingress_第7张图片
以下 Ingress 告诉后端负载均衡器根据 Host 标头路由请求:
service/networking/name-virtual-host-ingress.yaml:
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
如果您创建了一个没有在规则中定义任何主机的 Ingress 资源,则可以匹配到您的 Ingress 控制器 IP 地址的任何 Web 流量,而无需基于名称的虚拟主机
例如,以下 Ingress 将对 first.bar.com 请求的流量路由到 service1,将 second.bar.com 请求到 service2,并将请求主机标头与 first.bar.com 和 second.bar.com 不匹配的任何流量路由到 service3 .
service/networking/name-virtual-host-ingress-no-third-host.yaml:
​apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: name-virtual-host-ingress-no-third-host
spec:
  rules:
  - host: first.bar.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service1
            port:
              number: 80
  - host: second.bar.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service2
            port:
              number: 80
  - http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service3
            port:
              number: 80

五、TLS

可以通过指定包含 TLS 私钥和证书的 Secret来保护 Ingress。 Ingress 资源仅支持单个 TLS 端口 443,并假定 TLS 在i ngress point 终止(到 Service 及其 Pod 的流量是明文形式)。 如果 Ingress 中的 TLS 配置部分指定了不同的主机,则它们根据通过 SNI TLS 扩展指定的主机名在同一端口上多路复用(前提是 Ingress 控制器支持 SNI)。 TLS的secret 必须包含名为 tls.crt 和 tls.key 的密钥,其中包含用于 TLS 的证书和私钥。 例如:

执行命令生成ssl证书:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=CHINA/O=EDU"

生成secret:

kubectl create secret tls testsecret-tls --key tls.key --cert tls.crt

或者yaml生成:testsecret-tls.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: testsecret-tls
  namespace: default
data:
  tls.crt: base64 encoded cert # 私钥文件crt值
  tls.key: base64 encoded key # ssl证书文件key值
type: kubernetes.io/tls
在 Ingress 中引用这个 secret 会告诉 Ingress controller 使用 TLS 保护从客户端到负载均衡器的通道。 您需要确保您创建的 TLS 机密来自包含通用名称 (CN) 的证书,也称为 https-example.foo.com 的完全限定域名 (FQDN)。
Note:
    请记住, TLS 不适用于默认规则,因为必须为所有可能的子域颁发证书。 因此,tls 部分中的主机需要显式匹配规则部分中的主机。
service/networking/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

六、通过Ingress暴露的域名访问

6.1、部署好nginx服务

nginx-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:           
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080
  type: NodePort
18-1、k8s 对外服务之ingress_第8张图片
NodePort方式访问外网:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx" # Nginx Ingress Controller 根据该注解自动发现 Ingress
spec:
  rules:
  - host: www.baidu2.com # 对外访问的域名
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc # 对外暴露的 Service 名称
            port:
              number: 80 # nginx service 监听的端口
​

6.2、通过helm部署 Nginx Ingress Controller

见章节二

6.3、创建ingress

test-ingress.yaml:  创建的 Ingress 必须要和对外暴露的 Service 在同一命名空间下!
​apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx" # Nginx Ingress Controller 根据该注解自动发现 Ingress
spec:
  rules:
  - host: www.baidu2.com # 对外访问的域名
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc # 对外暴露的 Service 名称
            port:
              number: 80 # nginx service 监听的端口
​
执行 kubectl apply -f  test-ingress.yaml创建ingress。
kubectl get ingress查看ingress:

6.4、通过ingress暴露域名访问

因为没有域名,简单模拟,在master节点机器的/etc/hosts添加 10.244.2.113 www.baidu2.com 注意10.244.2.113是Nginx Ingress Controller的IP。这种只能在集群内部访问( 访问端口是80 ),其他人电脑无法访问。
若要其他人电脑也能访问,则添加 192.168.11.45  www.baidu2.com , 192.168.11.45是ingress-nginx所在的主机,也是master节点。此时的访问地址: http://www.baidu2.com:31046/
master节点上直接用域名访问:curl  www.baidu2.com
18-1、k8s 对外服务之ingress_第9张图片
master节点虚拟机网页访问: http://www.baidu2.com
18-1、k8s 对外服务之ingress_第10张图片

6.5、https配置访问

见章节五
apiVersion: v1
kind: Secret
metadata:
  name: testsecret-tls
  namespace: default
data:
  tls.crt: base64 encoded cert # 私钥文件crt值
  tls.key: base64 encoded key # ssl证书文件key值
type: kubernetes.io/tls
18-1、k8s 对外服务之ingress_第11张图片
修改ingress文件:
​apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: www.baidu2.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80
  tls:
  - hosts:
    - www.baidu2.com
    secretName: testsecret-tls
验证https方式访问:
18-1、k8s 对外服务之ingress_第12张图片
看看ingress-controller的实现方式,进入ingress-controller的pod:
kubectl -n ingress-nginx exec -it ingress-nginx-controller-59f89cb466-q8xmw bash
查看nginx.conf文件,cat /etc/nginx/nginx.conf:
18-1、k8s 对外服务之ingress_第13张图片

6.6、集群外访问(外网访问)

在/etc/hosts文件添加10.244.2.113 www.baidu2.com,这种只能在集群内部访问(端口是80或者443),其他人电脑无法访问。
若要其他人电脑也能访问,则添加 192.168.11.45  www.baidu2.com , 192.168.11.45是ingress-nginx所在的主机,也是master节点。此时访问端口是31046(http访问)或32393(https访问)
在其他电脑上修改hosts文件,添加  192.168.11.45  www.baidu2.com。
其他电脑访问:
    配置https前:  http://www.baidu2.com:31046/
    配置https后:  https://www.baidu2.com:32393/
18-1、k8s 对外服务之ingress_第14张图片

6.7、再部署一个服务tomcat

k8s_tomcat.yaml:
apiVersion: v1
kind: Pod
metadata:
  name: k8s-tomcat
  labels:
    app: k8s
spec:
  containers:
    - name: k8s-tomcat
      image: tomcat
      ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: k8s-tomcat-svc
spec:
  selector:
    app: k8s
  type: NodePort
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

执行命令kubectl apply -f k8s_tomcat.yaml部署tomacat。

修改ingress文件:test-ingress.yaml
​apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: www.baidu2.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80
  - host: tomact.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: k8s-tomcat-svc
            port:
              number: 8080
  tls:
  - hosts:
    - www.baidu2.com
    - tomact.com
    secretName: testsecret-tls
在其他电脑上修改hosts文件,添加  192.168.11.45  tomact.com, 网页访问: https://tomact.com:32393
18-1、k8s 对外服务之ingress_第15张图片

七、参考

Ingress | Kubernetes  
Installation Guide - NGINX Ingress Controller
【k8s】kubernetes之ingress error: endpoints “default-http-backend“ not found_云川之下的博客-CSDN博客
k8s之Ingress 实现 http 代理访问 - wangzy-Zj - 博客园

你可能感兴趣的:(k8s+docker,kubernetes,ingress)