纵有疾风起
人生不言弃

ASP.NET Core on K8S学习之旅(12)Ingress

本篇已加入《.NET Core on K8S学习实践系列文章索引》,可以点击查看更多容器化技术相关系列文章。

一、关于Ingress

  Kubernetes对外暴露Service主要有三种方式:NodePortLoadBalancer 以及 Ingress。前两种我们在第四篇《你必须知道的Service》一文中已经加以介绍,这里我们主要来看看Ingress是个什么鬼。

  官网对 Ingress 的定义为 管理对外服务到集群内服务之间规则的集合,通俗点讲就是它定义规则来允许进入集群的请求被转发到集群中对应服务上,从来实现服务暴漏。Ingress 能把集群内 Service 配置成外网能够访问的 URL,流量负载均衡,终止SSL,提供基于域名访问的虚拟主机等等。

  我们可以再次回顾一下我们通常访问一个业务的流程:

  • User在浏览中输入一个域名
  • DNS至业务入口,这里一般指外部负载均衡器(Load Balancer),比如阿里云的SLB服务
  • 外部负载均衡器反向代理到K8S的入口,比如Ingress
  • Ingress将请求转交给对应的Service
  • Service将请求对应到某一个具体的Pod  

ASP.NET Core on K8S学习之旅(12)Ingress插图

  了解了整个流程,我们再结合官网的定义来看Ingress,可以知道Ingress就是一个K8S集群业务的入口,一个统一访问入口。我们可以使用Traefik、Istio、Nginx、HAProxy来作为Ingress使用,这里我们主要介绍Nginx Ingress,因为我们比较熟悉Nginx一些。

二、Nginx Ingress的安装与配置

  这里我们在k8s-master上执行以下的yaml文件来通过DaemonSet的方式部署Nginx Ingress,这个yaml文件可以从ingress-nginx的github上获取,这里我选择的是0.30.0版本。

  获取方式:https://github.com/kubernetes/ingress-nginx/tree/nginx-0.30.0/deploy

ASP.NET Core on K8S学习之旅(12)Ingress插图1

ASP.NET Core on K8S学习之旅(12)Ingress插图2

   在static目录下,将mandatory.yaml文件获取下来如下代码所示,这里我做了一点修改(注意我标红的配置):

  (1)将原本为Deployment的类型换为了DaemonSet

  (2)为Ingress-Controller增加hostNetwork: true的配置,即直接占用宿主机80/443端口

  (3)将Ingress-Controller部署到有ingressHost: yes这个label的Node节点上,即我的k8s-node1服务器上

  (4)将Ingress-Controller的镜像源改为阿里云镜像仓库:registry.cn-hangzhou.aliyuncs.com

apiVersion: v1kind: Namespacemetadata:  name: ingress-nginx  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata:  name: nginx-configuration  namespace: ingress-nginx  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata:  name: tcp-services  namespace: ingress-nginx  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata:  name: udp-services  namespace: ingress-nginx  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/part-of: ingress-nginx---apiVersion: v1kind: ServiceAccountmetadata:  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/v1beta1kind: ClusterRolemetadata:  name: nginx-ingress-clusterrole  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/part-of: ingress-nginxrules:  - 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/v1beta1kind: Rolemetadata:  name: nginx-ingress-role  namespace: ingress-nginx  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/part-of: ingress-nginxrules:  - 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/v1beta1kind: RoleBindingmetadata:  name: nginx-ingress-role-nisa-binding  namespace: ingress-nginx  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/part-of: ingress-nginxroleRef:  apiGroup: rbac.authorization.k8s.io  kind: Role  name: nginx-ingress-rolesubjects:  - kind: ServiceAccount    name: nginx-ingress-serviceaccount    namespace: ingress-nginx---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata:  name: nginx-ingress-clusterrole-nisa-binding  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/part-of: ingress-nginxroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: nginx-ingress-clusterrolesubjects:  - kind: ServiceAccount    name: nginx-ingress-serviceaccount    namespace: ingress-nginx---apiVersion: apps/v1kind: DaemonSetmetadata:  name: nginx-ingress-controller  namespace: ingress-nginx  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/part-of: ingress-nginxspec:  # 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:      # wait up to five minutes for the drain of connections      terminationGracePeriodSeconds: 300      serviceAccountName: nginx-ingress-serviceaccount      nodeSelector:        kubernetes.io/os: linux        ingressHost: "yes"      hostNetwork: true      containers:        - name: nginx-ingress-controller          image: registry.cn-hangzhou.aliyuncs.com/google_containers/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---apiVersion: v1kind: LimitRangemetadata:  name: ingress-nginx  namespace: ingress-nginx  labels:    app.kubernetes.io/name: ingress-nginx    app.kubernetes.io/part-of: ingress-nginxspec:  limits:  - min:      memory: 90Mi      cpu: 100m    type: Container

   这里顺便说下Ingress的两种部署方式:

  (1)基于NodePort方式

ASP.NET Core on K8S学习之旅(12)Ingress插图3

   基于NodePort的部署思路就是通过在每个节点上开辟NodePort的端口,将流量引入进来,而后通过iptables首先转发到ingress-controller容器中(图中的nginx容器),而后由nginx根据ingress的规则进行判断,将其转发到对应的应用web容器中。

  (2)基于HostNetwork方式

ASP.NET Core on K8S学习之旅(12)Ingress插图4

  相比较起来,HostNetwork模式不再需要创建一个nodePort的svc,而是直接在每个节点都创建一个ingress-controller的容器,而且将该容器的网络模式设为HostNetwork。也就是说每个节点物理机的80和443端口将会被ingress-controller中的nginx容器占用。当流量通过80/443端口进入时,将直接进入到nginx中。而后nginx根据ingress规则再将流量转发到对应的web应用容器中。

  OK,两种模式我们就了解到这里,本文采用的是基于hostNetwork的方式占用宿主机80/443端口来作为流量入口。

  然后,我们就可以运行创建命令来创建Ingress-Controller了:

kubectl apply -f mandatory.yaml

  执行后的显示如下图所示,它会执行一系列的创建工作如namespace、configmap、serviceaccount、rbac以及daemonset等:

ASP.NET Core on K8S学习之旅(12)Ingress插图5

   Ingress-Controller创建好之后,我们再来创建一个指导Ingress进行路由转发的规则集ingress-nginx.yaml,其配置如下:

apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata:  name: nginx-ingress  namespace: xdp-poc  annotations:    kubernetes.io/ingress.class: "nginx"    nginx.ingress.kubernetes.io/rewrite-target: /api/$2spec:  rules:  - host: portal.k8s.xi-life.cn    http:      paths:      - path: /apple(/|$)(.*)        backend:          serviceName: apple-api-svc          servicePort: 80      - path: /banana(/|$)(.*)        backend:          serviceName: banana-api-svc          servicePort: 80

  它的作用其实是帮助Nginx生成正确的Nginx.conf,帮助Nginx将请求转发不同的K8s集群中的Service入口进行处理。这里,我定义了两个后端Service服务,稍后我会介绍这两个Service,现在我们现将其创建一下:

kubectl apply -f ingress-nginx.yaml

  好了,搭建和配置部分到此为止,下面我们可以准备刚刚提到的两个Service来进行一个简单的验证了。

三、Nginx Ingress的使用验证

3.1 WebAPI项目准备

  这里我准备两个ASP.NET Core WebAPI项目,他们的代码很简单,就只有一个HomeController,负责请求到api/home路由时返回一个json即可。

  其中,AppleApi项目返回:

// GET api/home[HttpGet]public ActionResult<IEnumerable<string>> Get(){    return new string[] { "AppleApi-Home", "v1.0", "Welcome to use AppleApi!" };}

  BananApi项目返回:

// GET api/home[HttpGet]public ActionResult<IEnumerable<string>> Get(){    return new string[] { "BananaApi-Home", "v1.0", "Welcome to use BananaApi!" };}

  这部分的代码文件可以在我的github上获取:点此获取

ASP.NET Core on K8S学习之旅(12)Ingress插图6

  然后,我们将这两个项目分别打一个docker镜像并上传到docker hub上,你可以直接使用我的镜像进行这个实验,具体的打包镜像和上传镜像的过程我就不演示了。

ASP.NET Core on K8S学习之旅(12)Ingress插图7

  直接拉取镜像:docker pull xilife/apple-api-demo:1.0 / docker pull xilife/banana-api-demo:1.0 

3.2 部署yaml文件准备

  接下来,我们就分别为两个API项目准备部署yaml文件,并应用该yaml文件创建pod和service:

  (1)deploy-appleapi-svc.yaml

apiVersion: apps/v1kind: Deploymentmetadata:  name: apple-api-demo  namespace: xdp-poc  labels:    name: apple-api-demospec:  replicas: 2  selector:    matchLabels:      name: apple-api-demo  template:    metadata:      labels:        name: apple-api-demo    spec:      containers:      - name: apple-api-demo        image: edisonsaonian/apple-api-demo:1.0        ports:        - containerPort: 80        imagePullPolicy: IfNotPresent---kind: ServiceapiVersion: v1metadata:  name: apple-api-svc  namespace: xdp-pocspec:  type: NodePort  ports:    - port: 80      targetPort: 80  selector:    name: apple-api-demo

  需要注意的就是:确保这里Service中定义的namespace(这里是xdp-poc)、服务名(这里是apple-api-svc)以及端口(这里是80)跟之前我们在ingress-nginx.yaml中设置的后端服务名和端口保持一致,否则无法实现请求转发。下面的BananaApi也是需要保持一致,就不再赘述。

  (2)deploy-bananaapi-svc.yaml

apiVersion: apps/v1kind: Deploymentmetadata:  name: banana-api-demo  namespace: xdp-poc  labels:    name: banana-api-demospec:  replicas: 2  selector:    matchLabels:      name: banana-api-demo  template:    metadata:      labels:        name: banana-api-demo    spec:      containers:      - name: banana-api-demo        image: edisonsaonian/banana-api-demo:1.0        ports:        - containerPort: 80        imagePullPolicy: IfNotPresent---kind: ServiceapiVersion: v1metadata:  name: banana-api-svc  namespace: xdp-pocspec:  type: NodePort  ports:    - port: 80      targetPort: 80  selector:    name: banana-api-demo

  最后,我们将其部署到K8s集群:

kubectl apply -f deploy-appleapi-svckubectl apply -f deploy-bananaapi-svc

  现在可以通过kubectl看看是否已经Running:

ASP.NET Core on K8S学习之旅(12)Ingress插图8

3.3 快速验证Ingress

   由于我们设置的host是portal.k8s.xi-life.cn,因此我们现在自己的客户机上修改一下hosts文件(Windows的话在system32/etc/drivers/hosts)增加一条记录,然后就可以通过浏览器输入域名来进行访问测试了:

   (1)apple-api

ASP.NET Core on K8S学习之旅(12)Ingress插图9

  (2)banana-api

ASP.NET Core on K8S学习之旅(12)Ingress插图10

四、小结

  本文介绍了Ingress的基本概念与Nginx Ingress的安装与配置,然后通过部署两个ASP.NET Core WebAPI服务到K8s集群进行Ingress的快速验证。当然,我们也可以使用自己的网关来代替Ingress作为外部统一流量入口,也可以使用云产品的LoadBalancer或API网关来替代Ingress也都是可以的(不缺钱的情况下)。

参考资料

(1)梁宽,《再也不踩坑的Kubernetes实战指南

(2)李振良,《一天入门Kubernets教程

(3)马哥(马永亮),《Kubernetes快速入门

(4)花田犯的错,《K8S Nginx Ingress介绍

(5)Lucie_xxm,《Ingress 统一访问入口

 

ASP.NET Core on K8S学习之旅(12)Ingress插图11

 

文章转载于:https://www.cnblogs.com/edisonchou/p/aspnet_core_on_k8s_deepstudy_part12.html

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » ASP.NET Core on K8S学习之旅(12)Ingress
分享到: 生成海报

评论 抢沙发

评论前必须登录!

立即登录