草庐IT

Kubernetes(k8s)Ingress原理

技术栈 2023-03-28 原文

一、概述

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

1)LoadBlancer Service

LoadBlancer Service 是 Kubernetes 结合云平台的组件,如国外 GCE、AWS、国内阿里云等等,使用它向使用的底层云平台申请创建负载均衡器来实现,有局限性,对于使用云平台的集群比较方便。

2)NodePort Service

NodePort Service 是通过在节点上暴漏端口,然后通过将端口映射到具体某个服务上来实现服务暴漏,比较直观方便,但是对于集群来说,随着 Service 的不断增加,需要的端口越来越多,很容易出现端口冲突,而且不容易管理。当然对于小规模的集群服务,还是比较不错的。

3)Ingress

Ingress 使用开源的反向代理负载均衡器来实现对外暴漏服务,比如 Nginx、Apache、Haproxy等。Nginx Ingress 一般有三个组件组成:

  • ingress是kubernetes的一个资源对象,用于编写定义规则。
  • 反向代理负载均衡器,通常以Service的Port方式运行,接收并按照ingress定义的规则进行转发,通常为nginx,haproxy,traefik等,本文使用nginx
  • ingress-controller,监听apiserver,获取服务新增,删除等变化,并结合ingress规则动态更新到反向代理负载均衡器上,并重载配置使其生效。

以上三者有机的协调配合起来,就可以完成 Kubernetes 集群服务的暴漏。

二、Ingress-nginx介绍

1)Ingress-nginx组成

  • ingress-nginx-controller:根据用户编写的ingress规则(创建的ingress的yaml文件),动态的去更改nginx服务的配置文件,并且reload重载使其生效(是自动化的,通过lua脚本来实现)
  • ingress资源对象:将Nginx的配置抽象成一个Ingress对象,每添加一个新的Service资源对象只需写一个新的Ingress规则的yaml文件即可(或修改已存在的ingress规则的yaml文件)

2)Ingress-nginx工作流程

Ingress 的实现分为两个部分 Ingress Controller 和 Ingress .

截至目前,nginx-ingress 已经能够完成 7/4 层的代理功能(4 层代理基于 ConfigMap,感觉还有改进的空间);Nginx 的 7 层反向代理模式,可以简单用下图表示:

  1. Nginx 对后端运行的服务(Service1、Service2)提供反向代理,在配置文件中配置了域名与后端服务 Endpoints 的对应关系。
  2. 客户端通过使用 DNS 服务或者直接配置本地的 hosts 文件,将域名都映射到 Nginx 代理服务器。
  3. 当客户端访问 service1.com 时,浏览器会把包含域名的请求发送给 nginx 服务器,nginx 服务器根据传来的域名,选择对应的 Service,这里就是选择 Service 1 后端服务,然后根据一定的负载均衡策略,选择 Service1 中的某个容器接收来自客户端的请求并作出响应。

过程很简单,nginx 在整个过程中仿佛是一台根据域名进行请求转发的“路由器”,这也就是7层代理的整体工作流程了!

3)工作原理

对于 Nginx 反向代理做了什么,我们已经大概了解了。在 k8s 系统中,后端服务的变化是十分频繁的,单纯依靠人工来更新nginx 的配置文件几乎不可能,nginx-ingress 由此应运而生。Nginx-ingress 通过监视 k8s 的资源状态变化实现对 nginx 配置文件的自动更新,下面本文就来分析下其工作原理。

  1. nginx-ingress 模块在运行时主要包括三个主体:NginxController、Store、SyncQueue。
  2. Store 主要负责从 kubernetes APIServer 收集运行时信息,感知各类资源(如 ingress、service等)的变化,并及时将更新事件消息(event)写入一个环形管道。
  3. SyncQueue 协程定期扫描 syncQueue 队列,发现有任务就执行更新操作,即借助 Store 完成最新运行数据的拉取,然后根据一定的规则产生新的 nginx 配置,(有些更新必须 reload,就本地写入新配置,执行 reload),然后执行动态更新操作,即构造 POST 数据,向本地 Nginx Lua 服务模块发送 post 请求,实现配置更新。
  4. NginxController 作为中间的联系者,监听 updateChannel,一旦收到配置更新事件,就向同步队列 syncQueue 里写入一个更新请求。

三、安装Ingress-nginx

1)官方介绍

ingress 官方网站
ingress 仓库地址

ingress-nginx v1.0 最新版本 v1.0
适用于 Kubernetes 版本 v1.19+ (包括 v1.19 )
Kubernetes-v1.22+ 需要使用 ingress-nginx>=1.0,因为networking.k8s.io/v1beta 已经移除

2)直接部署 ingress-nginx

直接部署比较简单,直接拉去 girhub 的文件就可以了,如果遇到长时间无响应,可以终止任务从新拉取。

拉取镜像

$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.0/deploy/static/provider/baremetal/deploy.yaml

如果上面地址下载失败,可以使用我一下地址下载。如果使用官网的,可能需要换镜像地址,因为官网下载的镜像很大可能会失败。这里我使用的是下面的yaml文件创建ingress-controller

链接:https://pan.baidu.com/s/1fbqcy2bJMtmziJoXTbdK2g
提取码:8888

# 修改镜像地址
$ sed -i 's@k8s.gcr.io/ingress-nginx/controller:v1.0.0\(.*\)@willdockerhub/ingress-nginx-controller:v1.0.0@' deploy.yaml
$ sed -i 's@k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.0\(.*\)$@hzde0128/kube-webhook-certgen:v1.0@' deploy.yaml
$ kubectl apply -f deploy.yaml

如果上面镜像还是下载失败,可以先下载镜像,地址如下:

链接:https://pan.baidu.com/s/1Rj5pDIGc3p3BjTU4PeIGFA
提取码:8888

下载完镜像,执行如下命令导入镜像:

$ docker image load -i hzde0128-kube-webhook-certgen-v1.0.tar
$ docker image load -i willdockerhub-ingress-nginx-controller-v1.0.0.tar
$ docker images

执行

$ kubectl apply -f ingress-nginx.yaml

检查安装

Completed 状态的是正常的,可以忽略。

$ kubectl get pod -n ingress-nginx
$ kubectl get svc -n ingress-nginx
$ kubectl get svc -n ingress-nginx

四、创建nginx应用

1)创建目录

$ mkdir -p /opt/ingress/nginx-test
$ cd /opt/ingress/nginx-test

2)创建nginx-Deployment-Service.yaml文件,内容如下:

$ cat << EOF > nginx-Deployment-Service.yaml
apiVersion: apps/v1 
kind: Deployment   
metadata:             
  name: nginx-deployment     
  labels:       
    app: nginx  
spec:          
  replicas: 2 
  selector:      
    matchLabels: 
      app: nginx
  minReadySeconds: 1
  progressDeadlineSeconds: 60
  revisionHistoryLimit: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:        
    metadata:  
      labels:  
        app: nginx
    spec:         
      containers:     
      - name: nginx     
        image: nginx:1.17.1    
        imagePullPolicy: Always          
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "1Gi"
            cpu: "80m"
          limits: 
            memory: "1Gi" 
            cpu: "80m"
---
apiVersion: v1
kind: Service
metadata:      
  name: nginx-service
  labels:      
    app: nginx
spec:        
  selector:   
    app: nginx
  ports:
  - name: nginx-port 
    protocol: TCP      
    port: 80  
    targetPort: 80
  type: ClusterIP 
EOF

3)部署 nginx应用

$ kubectl apply -f nginx-Deployment-Service.yaml
$ kubectl get svc -o wide|grep nginx-service
$ kubectl get pod -o wide|grep nginx-deployment-*

4)创建 ingress yaml文件,内容如下:

cat << EOF > nginx-Ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: ingress.nginx.com
    http:
      paths:
      - path: "/"
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80
EOF

创建

$ kubectl apply -f nginx-Ingress.yaml
$ kubectl get ingress|grep nginx

5)在 hosts 文件最后追加 ingress 节点的 IP 地址

$ kubectl get ingress|grep nginx
$ cat /etc/hosts
$ kubectl get svc -n ingress-nginx

6)验证

curl -I http://ingress.nginx.com:31473

五、使用 hostNetwork 的方式部署 ingress-nginx

每次部署 ingres-nginx 都随机一个 nodePort ,而使用 ingres-nginx 访问的时候也要以 域名:端口 的形式去访问,如何直接使用域名去访问呢?下面介绍另外一种安装方式。

1)创建目录

$ mkdir /opt/ingress/nginx-test/hostNetwork
$ cd  /opt/ingress/nginx-test/hostNetwork

2)copy 一份deploy.yaml

$ cp /opt/ingress/deploy.yaml /opt/ingress/nginx-test/hostNetwork/

3)优化 ingress-nginx

1、使用 hostNetwork

默认 ingress-nginx 随机提供 nodeport 端口,开启 hostNetwork 启用80、443端口。

修改 Deployment 下面的 spec
参数如下:

hostNetwork: true # 新增

2、修改负载均衡问题

把 kind: Deployment 改为 kind: DaemonSet 模式,这样每台 node 上都有 ingress-nginx-controller pod 副本。

参数如下:

kind: Deployment # 注释
kind: DaemonSet # 新增

3、修改 ingressClass 问题

如果不关心 ingressClass 或者很多没有 ingressClass 配置的 ingress 对象,
添加参数 ingress-controller --watch-ingress-without-class=true 。

4、部署检查 ingress

$ kubectl apply -f deploy.yaml

发现除了master节点,其它node节点都有一个副本。
在其它节点上查看node

$ netstat  -pntl |grep :443
$ netstat  -pntl |grep :80

5、验证

# 直接访问,不通过nodePort
$ curl -I  http://ingress.nginx.com
# 当然也可以通过nodePort访问
$ curl -I  http://ingress.nginx.com:31827

六、 基于HTTPS的Ingress-nginx

1)创建CA证书

$ mkdir -p /opt/ingress/tls
$ cd /opt/ingress/tls
# 生成ca证书,参数可根据需求自定义
$ openssl genrsa -out tls.key 2048
$ openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Shanghai/L=Shanghai/O=DevOps/CN=ingress.nginx.com

PS:CN必须为访问的域名相同

创建完成后,会在当前目录下生成证书密钥(tls.crt)和证书key(tls.key)文件:

2)secret简介

secret 用于存储和管理一些敏感数据,比如密码,token,密钥等敏感信息。它把 Pod 想要访问的加密数据存放到 Etcd 中。然后用户就可以通过在 Pod 的容器里挂载 Volume 的方式或者 环境变量 的方式访问到这些 Secret 里保存的信息。

Secret 可分为四种类型:

  • kubernetes.io/dockerconfigjson : 用来存储私有docker registry的认证信息
  • Opaque(generic:通用):从本地 file, directory 或者 literal value( literal:字面量) 创建一个 secret。对应的API对象为 Opaque([oʊˈpeɪk]),译为”不透明物”,等同于”敏感数据”。
  • kubernetes.io/tls:创建一个 TLS secret。
  • kubernetes.io/service-account-token:用于被serviceaccount引用。serviceaccout创建时Kubernetes会默认创建对应的secret。Pod如果使用了serviceaccount,对应的secret会自动挂载到Pod目录/run/secrets/ kubernetes.io/serviceaccount中。

Secret 示意图


3)创建 secret

上面了解了secret之后,就开始创建secret。自签证书生成后就可以用证书key和证书密钥创建 secret 了,这里为了方便,我用的是正规机构颁发的证书,如下所示:

$ cd /opt/ingress
$ ls tls/

1、通过命令行创建secret:

kubectl create secret tls ${CERT_NAME} --key ${KEY_FILE} --cert $

示例如下:

$ kubectl create secret tls tls-secret --key tls/tls.key --cert tls/tls.crt
$ kubectl get secret

2、通过yarml文件创建secret

yaml文件模板

apiVersion: v1
kind: Secret
metadata:
  name: testsecret-tls
  namespace: dashboard
data:
  tls.crt: base64 编码的 cert
  tls.key: base64 编码的 key
type: kubernetes.io/tls

示例:
获取base64 编码的 cert和base64 编码的 key

$ cd /opt/secret
$ cat tls/tls.crt | base64 > tls/base64.tls.crt
$ cat tls/tls.key | base64 > tls/base64.tls.key

这种方式创建有问题,会有如下报错,后续再研究。

4)创建deployment,service,ingress资源

1)切到对应的目录下

$ cd /opt/ingress

2)创建命令空间

$ cat << EOF > ingress-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ingress-test
EOF
$ kubectl apply -f ingress-namespace.yaml

3)创建secret

$ kubectl create secret tls tls-secret --key tls/tls.key --cert tls/tls.crt -n ingress-test
$ kubectl get secret -n ingress-test

4)创建deployment,service

$ cat << EOF > create-deployment-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: ingress-test
spec:
  replicas: 1
  selector:
    matchLabels:
     app: test-web
  template:
    metadata:
      labels:
        app: test-web
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
---
apiVersion: v1    #创建service,关联上述deployment
kind: Service
metadata:
  name: web-svc
  namespace: ingress-test
spec:
  selector:
    app: test-web
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
EOF
$ kubectl apply -f create-deployment-service.yaml

5)创建Ingress

$ cat << EOF > test-ingress.yaml
apiVersion: networking.k8s.io/v1  #创建ingress规则
kind: Ingress
metadata:
  name: test-ingress
  namespace: ingress-test
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:          #为域名颁发证书
    - hosts:
      - ingress.nginx.com
      secretName: tls-secret
  rules:
    - host: ingress.nginx.com
      http:   #注意,此处字段为http,不支持https
        paths:
        - path: /index.html
          pathType: Prefix
          backend:
            service:
              name: web-svc
              port:
                number: 80
EOF
$ kubectl apply -f test-ingress.yaml
$ kubectl get service -n ingress-test
$ kubectl describe ingress test-ingress -n ingress-test

6)通过ingress代理的443端口访问nginx服务

因为我们没有搭建dns服务器,所以需要在hosts文件将新的域名进行绑定(地址可以绑定集群中任意一台node)

$ kubectl get ingress -n ingress-test

在hosts文件中绑定域名:

192.168.0.114 ingress.nginx.com

7)https验证

# 查看ingress-nginx
$ kubectl get svc -n ingress-nginx
# 直接访问,-k:允许curl使用非安全的ssl连接并且传输数据(证书不受信)
$ curl -I -k https://ingress.nginx.com/
# 使用nodePort访问
$ curl -I -k https://ingress.nginx.com/31125

浏览器访问验证,https://ingress.nginx.com/

关于Kubernetes(k8s)Ingress的介绍就先到这里了,有疑问的小伙伴,欢迎给我留言哦~

有关Kubernetes(k8s)Ingress原理的更多相关文章

  1. 【Unity游戏破解】外挂原理分析 - 2

    文章目录认识unity打包目录结构游戏逆向流程Unity游戏攻击面可被攻击原因mono的打包建议方案锁血飞天无限金币攻击力翻倍以上统称内存挂透视自瞄压枪瞬移内购破解Unity游戏防御开发时注意数据安全接入第三方反作弊系统外挂检测思路狠人自爆实战查看目录结构用il2cppdumper例子2-森林whoishe后记认识unity打包目录结构dll一般很大,因为里面是所有的游戏功能编译成的二进制码游戏逆向流程开发人员代码被编译打包到GameAssembly.dll中使用il2ppDumper工具,并借助游戏名_Data\il2cpp_data\Metadata\global-metadata.dat

  2. Slowloris DoS攻击的原理与简单实现 - 2

    前言    Slowloris攻击是我在李华峰老师的书——《MetasploitWeb 渗透测试实战》里面看的,感觉既简单又使用,现在这种攻击是很容易被防护的啦。不过我也不敢真刀实战的去试,只是拿个靶机玩玩罢了。         废话还是写在结语里面吧。(划掉)结语可以不看(划掉)Slowloris攻击的原理        Slowloris是一种资源消耗类DoS攻击,它利用部分HTTP请求进行操作。也叫做慢速攻击,这里的慢速并不是说发动攻击慢,而是访问一条链接的速度慢。Slowloris攻击的功能是打开与目标Web服务器的连接,然后尽可能长时间的保持这些连接打开。如果由多台电脑同时发起Slo

  3. k8s-污点 (Taint)和容忍 (Tolerations) - 2

    文章目录一、污点(Taint)1、污点简介2、污点的组成3、污点的设置和去除二、容忍(Tolerations)1、容忍简介2、容忍的基本用法3、示例4、多污点与多容忍配置三、警戒(cordon)和转移(drain)四、Pod启动阶段(相位phase)五、故障排除步骤一、污点(Taint)节点亲和性,是Pod的一种属性(偏好或硬性要求),它使Pod被吸引到一类特定的节点Taint则相反,它使节点能够排斥一类特定的PodTaint和Toleration相互配合,可以用来避免Pod被分配到不合适的节点上。每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的Pod,是不会被

  4. [蓝桥杯单片机]学习笔记——串口通信的基本原理与应用 - 2

    目录一、原理部分1、什么是串行通信(1)并行通信与串行通信(2)串行通信的制式(3)串行通信的主要方式  2、配置串口(1)SCON和PCON:串行口1的控制寄存器(2)SBUF:串行口数据缓冲寄存器 (3)AUXR:辅助寄存器​编辑(4)ES、PS:与串行口1中断相关的寄存器(5)波特率设置  3、串口框架编写二、程序案例一、原理部分1、什么是串行通信(1)并行通信与串行通信微控制器与外部设备的数据通信,根据连线结构和传送方式的不同,可以分为两种:并行通信和串行通信。并行通信:数据的各位同时发送与接收,每个数据位使用一条导线,这种方式传输快,但是需要多条导线进行信号传输。串行通信:数据一位一

  5. kubernetes集群划分节点 - 2

    Kubernetes(K8s)是一个用于管理容器化应用程序的开源平台,可以帮助开发人员更轻松地部署、管理和扩展应用程序。在Kubernetes中,集群划分是一种重要的概念,可以帮助我们更好地组织和管理集群中的节点和资源。本文将介绍如何使用Kubernetes对集群进行划分,并提供详细的操作示例,希望能够帮助读者更好地了解和使用Kubernetes平台。Node划分Node划分是将集群中的节点按照一定的规则进行划分。在Kubernetes中,可以使用NodeSelector和Affinity机制来实现Node划分。NodeSelectorNodeSelector是一种将Pod调度到符合特定节点标

  6. 云原生(十八) | Kubernetes篇之Kubernetes(k8s)工作负载 - 2

    文章目录Kubernetes(k8s)工作负载一、Workloads二、Pod三、Deployment四、RC、RS、DaemonSet、StatefulSet五、Job、CronJob1、Job2、CronJob六、GCKubernetes(k8s)工作负载一、Workloads什么是工作负载(Workloads)工作负载是运行在Kubernetes上的一个应用程序。一个应用很复杂,可能由单个组件或者多个组件共同完成。无论怎样我们可以用一组Pod来表示一个应用,也就是一个工作负载Pod又是一组容器(Containers)所以关系又像是这样工作负载(Workloads)控制一组PodPod控制

  7. K8s部署PHP项目 - 2

    前言    前端时间PHP项目部署升级需要,需要把Laravel开发的项目部署K8s上,下面以laravel项目为例,讲解采用yaml文件方式部署项目。一、部署步骤1.创建Dockerfile文件Dockerfile是一个用来构建镜像的文本文件,在容器运行时,需要把项目文件和项目运行所必须的组件安装其中。#基础镜像FROMphp:7.4-fpm#时区ARGTZ=Asia/Shanghai#更换容器时区RUNcp"/usr/share/zoneinfo/$TZ"/etc/localtime&&echo"$TZ">/etc/timezone#替换成阿里apt-get源RUNsed-i"s@http

  8. ruby - # Ruby 中识别方法约定的基本原理/历史是什么? - 2

    例如,我一直看到称为String#split的方法,但从未见过String.split,这似乎更合乎逻辑。或者甚至可能是String::split,因为您可以认为#split位于String的命名空间中。当假定/隐含类(#split)时,我什至单独看到了该方法。我知道这是ri中识别方法的方式。哪个先出现?例如,这是为了区分方法和字段吗?我还听说这有助于区分实例方法和类方法。但这从哪里开始呢? 最佳答案 不同之处在于您如何访问这些方法。类方法使用::分隔符来表示消息可以发送到类/模块对象,而实例方法使用#分隔符表示消息可以发送到实例对

  9. H264压缩原理 - 2

    1、为什么压缩的原始数据一般采用YUV格式(1)利用人对图片感觉的生理特性,对于亮度信息比较敏感,对于色度信息不太敏感,所以视频编码是将Y分量和UV分量分开来编码,并且可以减少UV分量.2、视频压缩原理(1)空间冗余:图像相邻像素之间的相关性,比如一帧图片被划分成多个16x16的块之后,相邻的块之间有很多明显的相似性。(2)时间冗余:时间相差较近的两张图片变化较小。(3)视觉冗余:我们的眼睛对某些细节不太敏感,对图像中的高频信息的敏感度小于低频信息,可以去除一些高频信息。(4)编码冗余:一幅图片中不同像素出现的概率是不同的,对于出现次数较多的像素,用少的位数来编码,对于出现次数较少的像素,用多

  10. Python——程序的运行原理 - 2

    Python程序运行原理Python是一种脚本语言,编辑完成的程序,也称源代码,可以直接运行。从计算机的角度看,Python程序的运行过程包含两个步骤:解释器将源代码翻译成字节码(即中间码),然后由虚拟机解释执行。Python程序文件的扩展名通常为.py。在执行时,首先由Python解释器将.py文件中的源代码翻译成中间码,这个中间码是一个扩展名为.pyc的文件,再由Python虚拟机(PythonVirtualMachine,PVM)逐条将中间码翻译成机器指令执行。需要说明的是,pyc文件保存在Python安装目录的pycache文件夹下,如果Python无法在用户的计算机上写人字节码,字节

随机推荐