k8s服务发布Ingress

Kubernetes暴露服务的方式目前只有三种:LoadBlancer Service、NodePort Service、Ingress,通俗来讲,ingress和之前提到的Service、Deployment,也是一个k8s的资源类型,ingress用于实现用域名的方式访问k8s内部应用。

Ingress为Kubernetes集群中的服务提供了入口,可以提供负载均衡、SSL终止和基于名称的虚拟主机,在生产环境中常用的Ingress有Treafik、Nginx、HAProxy、Istio等。

一、基本概念

service的作用体现在两个方面,对集群内部,它不断跟踪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地址。这种用法仅用于在公有云服务提供商的云平台上设置 Service 的场景。受限于云平台,且通常在云平台部署LoadBalancer还需要额外的费用。在service提交后,Kubernetes就会调用CloudProvider在公有云上为你创建一个负载均衡服务,并且把被代理的Pod的IP地址配置给负载均衡服务做后端。

externalIPs:service允许为其分配外部IP,如果外部IP路由到集群中一个或多个Node上,Service会被暴露给这些externalIPs。通过外部IP进入到集群的流量,将会被路由到Service的Endpoint上。

Ingress:只需一个或者少量的公网IP和LB,即可同时将多个HTTP服务暴露到外网,七层反向代理。可以简单理解为service的service,它其实就是一组基于域名和URL路径,把用户的请求转发到一个或多个service的规则。

注意:

目前比较流行的IngressController有ingress-nginx( 由Kubemetes官方维护)、 nginx-ingress(由Nginx官方维护,注意和Ingress-nginx的区别)、Traefik、Istio等。

ingress-nginx(Kubemetes维护)

ingress:接口,编写规则--》yaml

ingress-controller:nginx

客户端(浏览器)---》地址栏(url)---》dns解析---》ip(安装了ingress-nginx的节点ip)-路由规则--》service---》pod

服务发布

重定向

前后端的分离(aaa.com,aaa.com/api)

htttps-->ssl 终结

身份认证

灰度发布(金丝雀发布)

1.Ingress 组成

1 ingress:

ingress是一个API对象,通过yaml文件来配置,ingress对象的作用是定义请求如何转发到service的规则,可以理解为配置模板。

ingress通过http或https暴露集群内部service,给service提供外部URL、负载均衡、SSL/TLS能力以及基于域名的反向代理。ingress要依靠 ingress-controller 来具体实现以上功能。

2 ingress-controller:

ingress-controller是具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。

ingress-controller并不是k8s自带的组件,实际上ingress-controller只是一个统称,用户可以选择不同的ingress-controller实现,目前,由k8s维护的ingress-controller只有google云的GCE与ingress-nginx两个,其他还有很多第三方维护的ingress-controller,具体可以参考官方文档。但是不管哪一种ingress-controller,实现的机制都大同小异,只是在具体配置上有差异。

一般来说,ingress-controller的形式都是一个pod,里面跑着daemon程序和反向代理程序。daemon负责不断监控集群的变化,根据 ingress对象生成配置并应用新配置到反向代理,比如ingress-nginx就是动态生成nginx配置,动态更新upstream,并在需要的时候reload程序应用新配置。

ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到 ingress-controller, 而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名、哪些URL要转发到哪些service等等。

2.Ingress工作过程

用户访问一个业务的流程如下:

(1)用户在浏览器中输入域名

(2)域名解析至业务的入口IP(一般为外部负载均衡器,比如阿里的SLB或者DMZ的网关)。

(3)外部负载均衡器反向代理至kubernetes的入口(一般为Ingress,或者通过NodePort暴露的服务等)。

(4)Ingress根据自身的配置找到对应的Service,再代理到对应的Service上。

(5)最后到达Service对应的某一个Pod上。

可见,在一般情况下,Ingress主要是一个用户kubernetes集群业务的入口。是业务能够 正常提供服务的核心,所以在生产环境中,推荐使用单独的服务器作为Ingress Controller。Controller可以使用Traefik、Istio、Nginx、HaProxy等作为Ingress Controller。因为相对于其他Ingress Controller,管理人员更熟悉Nginx或者HaProxy等服务,所以本章主要讲解Ingress Nginx的安装与常用配置,这也是kubernetes官方提供的Ingress Controller。

3.Ingress 工作原理

(1)ingress-controller通过和 kubernetes APIServer 交互,动态的去感知集群中ingress规则变化,

(2)然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置,

(3)再写到nginx-ingress-controller的pod里,这个ingress-controller的pod里运行着一个Nginx服务,控制器会把生成的 nginx配置写入 /etc/nginx.conf文件中,

(4)然后reload一下使配置生效。以此达到域名区分配置和动态更新的作用。

二、安装Ingress Nginx Controller

由于Ingress Controller相当于kubernetes集群中服务的"大门"因此在生产环境中,一定要保障Controller的稳定性和可用性。为了提高Ingress Controller的可用性,我们-般采用单独的服务器作为Controller节点,以此保障Ingress Controller的Pod资源不会被其他服务的Pod影响。

Ingress Nginx官方提供了多种部署方式,本节课将采用Helm的方式进行安装,并且将Ingress Controller安装在k8s-node0l节点。

1.下载并安装helm(已有helm环境可忽略此步骤)

[root@k8s-master ~]# wget https://get.helm.sh/helm-v3.9.4-linux-amd64.tar.gz
[root@k8s-master ~]# tar zxvf helm-v3.9.4-linux-amd64.tar.gz 
[root@k8s-master ~]# mv linux-amd64/helm /usr/local/bin/

2.下载并修改Ingress Controller参数(已有离线包可忽略此步骤)

[root@k8s-master ~]# helm repo \
add ingress-nginx https://kubernetes.github.io/ingress-nginx
"ingress-nginx" has been added to your repositories

[root@k8s-master ~]# helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "ingress-nginx" chart repository
Update Complete. ⎈Happy Helming!⎈

[root@k8s-master ~]# helm pull ingress-nginx/ingress-nginx --version 4.7.1
[root@k8s-master ~]# tar xvf ingress-nginx-4.7.1.tgz 
[root@k8s-master ~]# vim ingress-nginx/values.yaml 
(1)将Controller的registry仓库地址修改为国内的
controller:
    name: controller
    image:
        chroot: false
        registry: registry.cn-hangzhou.aliyuncs.com
        image: tanzu/controller
        tag: "v1.6.4"
        #digest: sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f
        #digestChroot: sha256:0de01e2c316c3ca7847ca13b32d077af7910d07f21a4a82f81061839764f8f81
(2)修改opentelemetry镜像地址
 opentelemetry:
    enabled: false
    image: registry.cn-hangzhou.aliyuncs.com/tanzu/opentelemetry:v20230107
    containerSecurityContext:
      allowPrivilegeEscalation: false
(3)将admissionWebhook的镜像地址修改为国内的
 patchWebhookJob:
      securityContext:
        allowPrivilegeEscalation: false
      resources: {}
    patch:
      enabled: true
      image:
        registry: registry.cn-hangzhou.aliyuncs.com
        image: tanzu/kube-webhook-certgen
        tag: v20220916-gd32f8c343
        #digest: sha256:543c40fd093964bc9ab509d3e791f9989963021f1e9e4c9c7b6700b02bfb227b
        pullPolicy: IfNotPresent
(4)修改hostNetwork的值为true

设置为true时,该Pod将与其所在节点共享网络命名空间。

(5)dnsPolicy设置为ClusterFirstWithHostNet

kubernetes可以在pod级别通过 dnspolicy字段设置DNS策略。目前支持的DNS策略如下:

  • Default: 继承pod所在宿主机的域名解析设置。
  • ClusterFirst: 将优先使用kubernetes环境的dns服务(如coreDNS提供的域名解析服务),将无法解析的域名转发到系统配置的上游DNS服务器。
  • ClusterFirstWithHostNet: 适用与以hostNetwork模式运行的pod。
  • None: 忽略集群的DNS配置,需要手工通过dnsConfig自定义DNS配置。这个选项在1.9版本中开始引入,到1.10版本时升级为Beta,到1.14版本时达到稳定版本。
(6)nodeSelector添加ingress: " true "
 nodeSelector:
    ingress: true
kubernetes.io/os: linux

此配置能够将ingress安装在带有"ingress: true"标签的节点上。

(7)修改kind类型为DeamonSet
kind: DeamonSet

注意:

如果已经下载好了离线的helm和ingress-nginx,可以直接解压并安装,不必下载。

3.部署ingress

(1)给需要部署Ingress Controller的节点打标签
[root@k8s-master ~]# kubectl label node k8s-node01 ingress=true
(2)创建namespace
[root@k8s-master ~]# kubectl create ns ingress-nginx
namespace/ingress-nginx created
(3)安装ingress-nginx
[root@k8s-master ~]# cd ingress-nginx

安装

[root@k8s-master ~]# helm install ingress-nginx -n ingress-nginx .

注意最后有一个点

卸载(不必要)

helm uninstall ingress-nginx -n ingress-nginx

查看安装信息

[root@master ~]# ku get pod -n ingress-nginx -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
ingress-nginx-controller-rbzvg   1/1     Running   0          61s   192.168.10.102   node1   <none>           <none>

三、Ingress Nginx入门

首先从最简单的配置开始,假如公司有一个web服务的容器,需要为其添加一个域名,此时可以使用Ingerss实现该功能。

1.创建一个用于学习的namespace

[root@k8s-master ~]# kubectl create ns study-ingress

2.创建一个nginx作为web服务

[root@master ~]# ku create deployment nginx --image=nginx:1.7.9 -n study-ingress
deployment.apps/nginx created

3.创建一个该web容器的Service

[root@master ~]# ku expose deployment nginx --port 80 -n study-ingress
service/nginx exposed

4.创建ingress指向上一步中的Service

[root@master ~]# vim web-ingress.yaml 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: study-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

备注:

路径类型

有3种支持的path类型:

  • ImplementationSpecific:对于这种path类型,匹配取决于IngressClass。可以将其视为一个单独的pathType或者将其认为和Prefix或者Exact路径类型一样。
  • Exact:精确匹配URL路径,并且区分大小写
  • Prefix: 根据URL中的,被/分割的前缀进行匹配。匹配区分大小写并且按照元素对路径进行匹配。path元素指的是路径中由/分隔符分隔的标签列表。
  • 注意:如果路径的最后一个元素是请求路径中最后一个元素的子字符串,那么这个是不匹配的。【举例:/foo/bar匹配/foo/bar/baz,但是不匹配/foo/barbaz

5.创建该ingress

[root@master ~]# ku create -f web-ingress.yaml 
ingress.networking.k8s.io/nginx-ingress created

注意:

不要删除此ingress,否则,后面的ssl无法访问

6.客户端访问测试

创建的Ingress绑定的域名为nginx.test.com,由于本书的IngressController是以hostNetwork模式部署的,因此将域名解析至IngressController所在的节点即可。如果IngressController上层还有一层网关,解析至网关IP即可。接下来通过域名nginx.test.com即可访问Web服务器。

可以看到通过上述简单的Ingress资源定义就可以实现以域名的方式访问服务,不需要再去维护复杂的Ngmx配置文件,大大降低了运维的复杂度和出错的频率。

接下来通过一些其他配置实现企业内常用的功能,比如重定向、前后端分离、错误友好页面等。

四、Ingress Nginx域名重定向Redirect

当一个服务需要更换域名时,并不能对其直接更改,需要一个过渡的过程。在这个过程中,需要将旧域名的访问跳转到新域名,此时可以使用Redirect功能。待旧域名无访问时,再停止旧域名。

在Nginx作为代理服务器时,Redirect可用于域名的重定向,比如访问old.com被重定向到new.com。Ingress可以更简单地实现Redirect功能。接下来用nginx.redirect.com作为旧域名,baidu.com作为新域名进行演示。

1.编辑Ingress文件

[root@master ~]# vim redirect.yaml 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com
  name: nginx-redirect
  namespace: study-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.redirect.com
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

2. 创建Ingress

[root@master ~]# ku create -f redirect.yaml 
ingress.networking.k8s.io/nginx-redirect created

3.测试

在客户端的hosts文件添加域名nginx.redirect.com,IP地址为k8s-node01节点的IP地址。

使用域名nginx.redirect.com访问网站,打开的是baidu,com,说明跳转成功。

五、Ingress Nginx前后端分离Rewrite

现在大部分应用都是前后端分离的架构,也就是前端用某个域名的根路径进行访问,后端接口采用/api进行访问,用来区分前端和后端。或者同时具有很多个后端,需要使用/api-a到A服务,/api-b到B服务,但是由于A和B服务可能并没有/api-a和/api-b的路径,因此需要将/api-x重写为"/",才可以正常到A或者B服务,否则将会出现404的报错。此时可以通过Rewrite功能达到这种效果。

1.创建一个应用模拟后端服务

[root@master ~]# ku create deployment backend-api --image=nginx:1.7.9 -n study-ingress
deployment.apps/backend-api created

2. 创建Service暴露应用

[root@master ~]# ku expose deployment backend-api --port 80 -n study-ingress
service/backend-api exposed

3. 查看该Service的地址,并通过/api-a访问测试

[root@master ~]# ku get svc -n study-ingress
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
backend-api   ClusterIP   10.108.200.70   <none>        80/TCP    3s
nginx         ClusterIP   10.108.137.55   <none>        80/TCP    64m

​​​​​​http://nginx.test.com/api-a

4. 编辑ingress,实现rewrite

[root@master ~]# vim rewirte.yaml 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: backend-api
  namespace: study-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
          service:
            name: backend-api
            port:
              number: 80
        path: /api-a(/|$)(.*)
        pathType: ImplementationSpecific

5. 创建该ingress

[root@master ~]# ku create -f rewirte.yaml 
ingress.networking.k8s.io/backend-api created

6.访问测试

http://nginx.test.com/api-a

六、 Ingress Nginx SSL配置

生产环境对外的服务一般需要配置HTTPS协议,使用Ingress也可以非常方便地添加HTTPS的证书°。

由于是学习环境,并没有权威证书,因此需要使用OpenSSL生成一个测试证书(如果是生产环境,那么证书为在第三方公司购买的证书,无须自行生成)。

1.生成证书

[root@master ~]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginx.test.com"
Generating a 2048 bit RSA private key
........................................................................................+++
......................................+++
writing new private key to 'tls.key'
-----

2. 创建证书的secret

[root@master ~]# ku create secret tls ca-secret --cert=tls.crt --key=tls.key -n study-ingress
secret/ca-secret created

3. 编辑ingress

[root@k8s-master ~]# vim ingress-ssl.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  creationTimestamp: null
  name: nginx-ingress-ssl
spec:
  ingressClassName: nginx-ssl
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:		##证书授权的域名列表
    - nginx.test.com
    secretName: ca-secret		##证书的secret名字

4. 创建此ingress

[root@master ~]# ku create -f ingress-ssl.yaml 
ingress.networking.k8s.io/nginx-ingress-ssl created

5. 访问测试

https://nginx.test.com

七、Ingress Nginx基本认证

有些网站可能需要通过密码来访问,对于这类网站可以使用nginx的basic-auth设置密码访问,具体方法如下,由于需要使用htpasswd工具,因此需要安装httpd。

1.安装httpd

[root@master ~]# yum -y install httpd

2. 使用htpasswd创建用户

[root@master ~]# htpasswd -c auth zhangsan
New password: 
Re-type new password: 
Adding password for user zhangsan

3. 基于之前创建的密码文件创建secret

[root@master ~]# ku create secret generic basic-auth --from-file=auth -n study-ingress
secret/basic-auth created

4.编辑ingress,包含密码认证

[root@master ~]# vim ingress-with-auth.yaml 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/auth-realm: Please Input Your Username and Password
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-type: basic
  name: ingress-with-auth
  namespace: study-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: auth.test.com
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

备注:

nginx.ingress.kubernetes.io/auth-secret: auth 密码文件的secret名称

nginx.ingress.kubernetes.io/auth-type: basic 认证类型

host: auth.test.com 客户端要访问的域名,注意不要使用前面的域名,或者把前面的ingress都删掉

5.部署此ingress

[root@master ~]# ku create -f ingress-with-auth.yaml 
ingress.networking.k8s.io/ingress-with-auth created

6.访问测试

在客户端添加域名auth.test.com的解析

相关推荐
伪装成塔的小兵4 小时前
Windows使用docker部署fastgpt出现的一些问题
windows·docker·容器·oneapi·fastgpt
寂夜了无痕4 小时前
k8s容器运行时环境选型指南
云原生·kubernetes·k8s运行时环境选择
元气满满的热码式5 小时前
logstash中的input插件(http插件,graphite插件)
网络·网络协议·http·elasticsearch·云原生
转身後 默落7 小时前
11.Docker 之分布式仓库 Harbor
分布式·docker·容器
Swift社区8 小时前
【微服务优化】ELK日志聚合与查询性能提升实战指南
spring·elk·微服务·云原生·架构
guihong0048 小时前
深入解析Zookeeper脑裂问题与CAP取舍:从原理到实战
分布式·zookeeper·云原生
菩提云8 小时前
Deepseek存算分离安全部署手册
人工智能·深度学习·安全·docker·容器
努力的小T18 小时前
使用 Docker 部署 Apache Spark 集群教程
linux·运维·服务器·docker·容器·spark·云计算
东风微鸣20 小时前
TTRSS 迁移实战
docker·云原生·kubernetes·可观察性
Smile_Gently1 天前
Docker
云原生·eureka