kubernetes的Ingress

什么是Ingress

Ingress对象,其实就是对反向代理的一种抽象,简单的说就是衣蛾全局的负载均衡器,可以通过访问URL定位到后端的Service

有了Ingress这个抽象,K8S就不需要关心Ingress的细节了,实际使用时,只需要选择一个具体的Ingress Controller部署就行了,业界常用的反向代理项目有:Nginx、HAProxy、Envoy、Traefik,都已经成为了K8S专门维护的Ingress Controller
一个Ingress对象的主要内容,就类似Nginx的配置文件描述,对应的转发规则就是ingressRule,
有了Ingress这个对象,用户就可以根据自己的需求选择Ingress Controller,例如,如果应用对代理服务的中断非常敏感,可以使用Treafik这样的Ingress Controller

Ingress工作在七层,Service工作在四层,当想要在Kubernetes里为应用进行TLS配置等HTTPS相关操作时,都必须通过Ingress来进行

LoadBalancer的Service也会在公有云创建负载均衡,但是是一个Servcie对应一个,太浪费了

以下以演示部署一个Nginx Ingress Controller,并代理一个我们自己创建的服务coffee

Nginx Ingress Controller 官网地址:https://kubernetes.github.io/ingress-nginx
依赖的其他github相关yaml文件:https://github.com/nginxinc/kubernetes-ingress/tree/master/examples/complete-example

pod与ingress的关系

•通过label-selector相关联
•通过Ingress Controller实现Pod的负载均衡
-支持TCP/UDP 4层和HTTP 7层

Ingress配置文件

apiVersion: extensions/v1beta1 
kind: Ingress 
metadata: 
  name: test-ingress 
  annotations: nginx.ingress.kubernetes.io/rewrite-target: / 
spec: 
  rules: 
  - http: 
    paths: 
    - path: /testpath 
      backend: 
        serviceName: test 
        servicePort: 80
  • 1-6:Ingress YAML文件中的1-6行与其它的Kubernetes配置文件一样,需要apiVersionkindmetadata字段。此示例定义了名称为test-ingress的Ingress。
  • 7-9:Ingress规格具有配置负载均衡器或代理服务器所需的所有信息。最重要的是,它包含与所有传入请求相匹配的规则列表。目前,Ingress资源仅支持http规则。
  • 10-11:每个http规则都包含以下信息:一个主机(例如:foo.ba.com,在这个例子中为*),一个路径列表(例如:/testpath),每个路径都有一个相关的后端(test:80)。在负载均衡器将业务引导到后端之前,主机和路径都必须匹配传入请求的内容。
  • 12-14:后端是服务:端口test:80组合。Ingress流量通常被直接发送到与后端相匹配的端点。

Ingress 组成

ingress controller:将新加入的Ingress转化成Nginx的配置文件并使之生效
ingress服务:将Nginx的配置抽象成一个Ingress对象,每添加一个新的服务只需写一个新的Ingress的yaml文件即可

Ingress类型

单个service资源型Ingress

apiVersion: extensions/v1beta1 
kind: Ingress 
metadata: 
  name: single-ingress 
spec: 
    backend: 
      serviceName: my-svc
      servicePort: 80

Ingress控制器会分配一个IP地址接入请求流量,并将他们转至my-svc后端

基于URL路径进行流量转发

通过主域名的URL(path)分别接入,例如:www.ilinux.io/api、www.ilinux.io/wap等等,用于发布集群内名称为API和WAP的service资源。

apiVersion: extensions/v1beta1 
kind: Ingress 
metadata: 
  name: single-ingress 
  annotations: 
ingress.kubernetes.io
/rewrite-target: / spec: rules: - host: www.ilinux.io http: paths: - path: /wap backend: serviceName: wap servicePort: 80
- path: /api
backend:
serviceName: api
servicePort: 80

基于主机名称的虚拟主机

上面类型2中可以将每个应用分别以独立的主机名输出,如wap.ik8s.io和api.ik8s.io,这两个主机名分别解析道externalLB的ip地址之上,分别用于发布集群内部的WAP和API两个service资源。

apiVersion: extensions/v1beta1 
kind: Ingress 
metadata: 
  name: test
spec: 
  rules: 
  - host: wap.ik8s.io
    http: 
      paths: 
      - path: /wap 
        backend: 
          serviceName: wap
          servicePort: 80
  - host: api.ik8s.io
    http: 
      paths: 
      - path: /api 
        backend: 
          serviceName: api
          servicePort: 80  

TLS类型的Ingress资源

这种类型用于HTTPS发布service资源,基于一个含有私钥和证书的secret对象,目前来说,Ingress资源仅支持单个TLS端口,并且会写在TLS会话。在Ingress资源中引用次Secret即可让Ingress控制器家在并配置HTTPS服务。

apiVersion: extensions/v1beta1 
kind: Ingress 
metadata: 
  name: no-rules-map
spec: 
  tls: 
  - secretName: ikubernetesSecret
  backend: 
      serviceName: wap
      servicePort: 80

使用Ingress

步骤如下所示

  • 部署ingress Controller【需要下载官方的】
  • 创建ingress规则【对哪个Pod、名称空间配置规则】

创建Nginx Pod

创建一个nginx应用,然后对外暴露端口

# 创建pod
kubectl create deployment web --image=nginx
# 查看
kubectl get pods

对外暴露端口

kubectl expose deployment web --port=80 --target-port=80 --type=NodePort

部署 ingress controller

下面我们来通过yaml的方式,部署我们的ingress,配置文件如下所示

kubectl apply -f https://github.com/kubernetes/ingress-nginx/blob/nginx-0.20.0/deploy/mandatory.yaml

内容如下

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx

---

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: default-http-backend
  labels:
    app.kubernetes.io/name: default-http-backend
    app.kubernetes.io/part-of: ingress-nginx
  namespace: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: default-http-backend
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: default-http-backend
        app.kubernetes.io/part-of: ingress-nginx
    spec:
      terminationGracePeriodSeconds: 60
      containers:
        - name: default-http-backend
          # Any image is permissible as long as:
          # 1. It serves a 404 page at /
          # 2. It serves 200 on a /healthz endpoint
          image: k8s.gcr.io/defaultbackend-amd64:1.5
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 30
            timeoutSeconds: 5
          ports:
            - containerPort: 8080
          resources:
            limits:
              cpu: 10m
              memory: 20Mi
            requests:
              cpu: 10m
              memory: 20Mi

---
apiVersion: v1
kind: Service
metadata:
  name: default-http-backend
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: default-http-backend
    app.kubernetes.io/part-of: ingress-nginx
spec:
  ports:
    - port: 80
      targetPort: 8080
  selector:
    app.kubernetes.io/name: default-http-backend
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: udp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: nginx-ingress-clusterrole
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
    resources:
      - ingresses/status
    verbs:
      - update

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: nginx-ingress-role
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - configmaps
    resourceNames:
      # Defaults to "<election-id>-<ingress-class>"
      # Here: "<ingress-controller-leader>-<nginx>"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-nginx"
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: nginx-ingress-role-nisa-binding
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nginx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nginx-ingress-clusterrole-nisa-binding
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nginx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      serviceAccountName: nginx-ingress-serviceaccount
      containers:
        - name: nginx-ingress-controller
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.20.0
          args:
            - /nginx-ingress-controller
            - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io
          securityContext:
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 33
            runAsUser: 33
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
            - name: https
              containerPort: 443
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1

---

通过这种方式,其实我们在外面就能访问,这里还需要在外面添加一层

kubectl apply -f ingress-con.yaml

image-20201118111256631

最后通过下面命令,查看是否成功部署 ingress

kubectl get pods -n ingress-nginx

image-20201118111424735

创建ingress规则文件

创建ingress规则文件,ingress-h.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test
spec:
  rules:
  - host: ingress.test.com
    http:
      paths:
      - path: /
        backend:
          serviceName: my-dep
          servicePort: 80

添加域名访问规则

在windows 的 hosts文件,添加域名访问规则【因为我们没有域名解析,所以只能这样做】

 最后通过域名就能访问

 参考资料:

1.《Ingress》地址:https://kubernetes.io/docs/concepts/services-networking/ingress/

2.《Rewrite》地址:https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/rewrite/README.md

posted @ 2020-12-17 15:27  fat_girl_spring  阅读(145)  评论(0编辑  收藏  举报