kubernetes对外服务之Ingress

目录

一、Ingress 是什么

1.1Service的作用

1.2Ingress简介

二、Ingress 安装

三、Ingress 代理访问

3.1Ingress HTTP 代理访问

3.2 Ingress: HTTPS 代理访问

3.3Ingress Contronler怎么工作的?


​​​​​​​​​​​​​​一、Ingress 是什么


1.1Service的作用

  • 对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制;
  • 对集群外部,他类似负载均衡器,可以在集群外部对pod进行访问。在Kubernetes中,Pod的IP地址和service的ClusterIP仅可以在集群网络内部做用,对于集群外的应用是不可见的。

为了使外部的应用能够访问集群内的服务,Kubernetes目前提供了以下几种方案:

  • NodePort:将service暴露在节点网络上,NodePort背后就是Kube-Proxy,Kube-Proxy是沟通service网络、Pod网络和节点网络的桥梁。测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的瑞口管理就是个灾难。因为每个端口只能是一种服务,端口范围只能是 30000-32767。
  • LoadBalancer:通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。这种用法仅用于在公有云服务提供商的云平台上设置Servic的场景。受限于云平台,且通常在云平台部署LoadBalancer还需要额外的费用。
  • Ingress:只需一个或者少量的公网IP和LB,即可同时将多个HTTP服务暴露到外网,七层反向代理。可以简单理解为service的service,它其实就是一组基于域名和URL路径,把用户的请求转发到一个或多个service的规则。
     

NodePort存在的不足:

• 一个端口只能一个服务使用,端口需提前规划

• 只支持4层负载均衡,使用 iptables或IPVS做分流,不支持基于域名或者URL的匹配

1.2Ingress简介

Ingress公开了从集群外部到集群内服务的HTTP和HTTPS路由的规则集合,而具体实现流量路由则是由Ingress Controller负责。

IngressK8s中的一个抽象资源,给管理员提供一个暴露应用的入口定义方法

Ingress Controller:根据Ingress生成具体的路由规则,并对Pod负载均衡器,提供统一的端口(80/443)

Ingress相当于一个7层的负载均衡器,是k8s对反向代理的一个抽象。大概的工作原理也确实类似于Nginx,可以理解成在 Ingress 里建立一个个映射规则 , ingress Controller 通过监听 Ingress这个api对象里的配置规则并转化成 Nginx 的配置(kubernetes声明式API和控制循环) , 然后对外部提供服务。

Ingress是一个API对象,通过yaml文件来配置,ingress对象的作用是定义请求如何转发到service的规则,可以理解为配置模板。
ingress通过http或https暴露集群内部service,给service提供外部URI、负载均衡、SSL/TLS能力以及基于域名的反向代理。ingress要依靠ingress-controiler来具体实现以上功能。

ingress包括:ingress controller和ingress resources

ingress controller:核心是一个deployment,实现方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,需要编写的yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的类型可以是NodePort或者LoadBalancer。

ingress resources:这个就是一个类型为Ingress的k8s api对象了,这部分则是面向开发人员。

Ingress解决的是新的服务加入后,域名和服务的对应问题,基本上是一个ingress的对象,通过yaml进行创建和更新进行加载。

Ingress Controller是将Ingress这种变化生成一段Nginx的配置,然后将这个配置通过Kubernetes API写到Nginx的Pod中,然后reload.(注意:写入 nginx.conf 的不是service的地址,而是service backend 的 pod 的地址,避免在 service 在增加一层负载均衡转发)(转载)


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

了解了以上内容以后,这也就很好的说明了我为什么喜欢把负载均衡器部署为 Daemon Set;因为无论如何请求首先是被负载均衡器拦截的,所以在每个 node 上都部署一下,同时 hostport 方式监听 80 端口;那么就解决了其他方式部署不确定 负载均衡器在哪的问题,同时访问每个 node 的 80 都能正确解析请求;如果前端再 放个 nginx 就又实现了一层负载均衡。

Ingress Controller 会根据你定义的 Ingress 对象,提供对应的代理能力。业界常用的各种反向代理项目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已经为Kubernetes 专门维护了对应的 Ingress Controller。(转载)在这里插入图片描述


二、Ingress 安装


Ingress Controller有很多实现,我们这里采用官方维护的Nginx控制器。

项目地址:GitHub - kubernetes/ingress-nginx: Ingress-NGINX Controller for Kubernetes

注意事项:

• 镜像地址修改成国内的:lizhenliang/nginx-ingress-controller:0.30.0

• 将Ingress Controller暴露,一般使用宿主机网络(hostNetwork: true)或者使用NodePort

其他控制器:Ingress Controllers | Kubernetes

下载 Ingress镜像:

wget --no-check-certificate  https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml

mandatory.yaml 部署

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    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:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    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: apps/v1
kind: DaemonSet
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  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:
      hostNetwork: true
      # wait up to five minutes for the drain of connections
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: nginx-ingress-controller
          image: lizhenliang/nginx-ingress-controller:0.30.0
          args:
            - /nginx-ingress-controller
            - --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:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 101
            runAsUser: 101
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
            - name: https
              containerPort: 443
              protocol: TCP
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown

部署 ingress-controller对外提供服务:

kubectl apply -f  ingress-controller.yaml
kubectl get pod  -n ingress-nginx -o wide

nginx-ingress-controller查看:


三、Ingress 代理访问


3.1Ingress HTTP 代理访问

创建 deployment和 svc :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web1
  namespace: default
  annotations:       # 记录回滚参数
  kubernetes.io/change-cause: "web.v1-nginx-1.17"   #记录到revision中的内容,记录版本号
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      containers:
      - name: web
        image: nginx:1.17

---
apiVersion: v1
kind: Service
metadata:
  name: web1
  namespace: default
spec:
  ports:
  - port: 80      # service端口
    protocol: TCP   # 协议
    targetPort: 80  # 容器端口
  selector:         # 标签选择器
    app: nginx      # 指定关联Pod的标签
  type: ClusterIP    # 服务类型

 启动 web1 pod 并暴露 ClusterIP 访问端口80

本地电脑绑定hosts记录对应ingress里面配置的域名例:创建 web1 Ingress :

​
apiVersion: networking.k8s.io/v1 
kind: Ingress
metadata: 
  name: web1 
spec:
  rules:
  - host: web1.ctnrs.com 
    http:
      paths:
      - path: / 
        pathType: Prefix 
        backend: 
          service:
            name: web1            
            port: 
              number: 80   ## clusterIP 端口

查看Ingress是否部署成功

windows 服务器主机 C:\Windows\System32\drivers\etc\hosts 添加域名映射关系

192.168.2.118 k8s-node1 web1.ctnrs.com

192.168.2.210 k8s-node2 web1.ctnrs.com

使用域名 web1.ctnrs.com 成功访问

3.2 Ingress: HTTPS 代理访问

配置HTTPS步骤:

1、准备域名证书文件(来自:openssl/cfssl工具自签或者权威机构颁发)

2、将证书文件保存到Secret

kubectl create secret tls blog-ctnrs-com --cert=blog.ctnrs.com.pem -- key=blog.ctnrs.com-key.pem

3、Ingress规则配置tls

apiVersion: networking.k8s.io/v1 
kind: Ingress
metadata: 
  name: blog 
spec:
  tls:
  - hosts: 
    - blog.ctnrs.com
    secretName: blog.ctnrs.com
  rules:
  - host: blog.ctnrs.com 
    http:
      paths:
      - path: / 
        pathType: Prefix 
        backend: 
          service:
            name: web1
            port: 
              number: 80

windows 服务器主机 C:\Windows\System32\drivers\etc\hosts 添加域名映射关系

192.168.2.118 k8s-node1 web1.ctnrs.com blog.ctnrs.com

192.168.2.210 k8s-node2 web1.ctnrs.com blog.ctnrs.com

由于是自签的证书,所以会报不可信证书,继续访问就可以

3.3Ingress Contronler怎么工作的?

下图<>里面代表资源类型,无此符号的部分是这个资源的名字,图中实线部分是实际访问流程,虚线部分是路由规则的维护。

流程分解:

企业级应用场景最常用的方式就是用外层4层或7层负载来保证后端服务的可用性,如图是负载nginx这个ingress-controller的svc

nginx-controller有自己的service,用的是nodeport模式对外暴露端口,关联后端ingress-controller

③ingress-controller拿到请求后转发给后端的service

④service通过标签选择器,找到后面对应的pod

*⑤ingress里面test.k8s.com这个域名的路由规则

*⑥ingress的规则会通过k8s-apiserver对外提供查询

*⑦ingress-controller查询k8s-apiserver拿到ingress路由规则,并更新在自己的配置文件里面

参考原文链接:k8s ingress-controller处理流程及原理_A � 戏 子、Libra的博客-CSDN博客

https://blog.csdn.net/yrx420909/article/details/105724292 

https://blog.51cto.com/u_15382481/5205194

猜你喜欢

转载自blog.csdn.net/qq_35995514/article/details/128070550