k8s容器编排技术实践——K8s中服务发现ingress、ingress controller 应用实践

k8s容器编排技术实践------k8s应用中机密信息的配置与存储https://blog.csdn.net/xiaochenXIHUA/article/details/161706954?spm=1001.2014.3001.5501k8s容器编排技术实践------k8s的介绍及其整体运行架构-CSDN博客https://coffeemilk.blog.csdn.net/article/details/161011629

一、ingress-nginx简介

1.1、Service机制的局限性

⚠️Service机制的局限性
只提供 4 层负载均衡,不支持7层负载均衡功能。
使用 NodePort 类型的 Service,需要在集群外部部署一个外部的负载均衡器。
使用 LoadBalancer类型的Service,Kubernetes 必须运行在特定的云服务上。
每创建一个Service NodePort类型,就会在每个节点开启一个端口,当项目多时,端口会难以维护。当项目很多时,Service的Iptables规则也随着数倍增多,如此多的iptables条目让增大维护和故障定位。

如何理解上面的局限性呢,如下是NodePort模式运行原理图:

1.2、ingress-nginx如何实现服务发现

针对上述问题,k8s官方提供了一种折中的方案:Ingress与Service不同,Ingress实际上不是一种服务。相反,它位于多个服务之前,充当集群中的智能路由器或入口点。ingress-nginx实现架构如下图所示:

Ingress是在Kubernetes 1.1 版本后引入的资源类型。Ingress 支持将 Service 暴露到 Kubernetes 集群外,同时可以自定义 Service 的访问策略。Ingress 能够把 Service 配置成外网能够访问的 URL,也支持提供按域名访问的虚拟主机功能(如:通过负载均衡器实现不同的二级域名到不同 Service 的访问)。

实际上 Ingress 只是一个统称,主要有【Ingress】、【Ingress Controller】和【Ingress-Controller-service】三部分组成。

Ingress构成 说明
Ingress 将原来需要手动配置的规则抽象成一个Ingress对象,使用YAML格式的文件来创建和管理。将请求转发给Ingress Controller。
Ingress Controller 核心组件,用作通过与Kubernetes API交互,动态感知集群中Ingress规则变化,并应用新配置,实现七层转发。
Ingress-Controller-service kuberntes中四层的负载均衡调度机制,Ingress借助service的服务发现机制实现集群中Pod资源的动态感知,用于接入外部流量;

Ingress Controller目前有多种软件负载均衡实现(如:Nginx、HAProxy等),而本文要讲解的是基于Nginx的Ingress Controller。在使用 Ingress前必须要先部署 Ingress Controller,Ingress Controller是以一种插件的形式提供。Ingress Controller通常是部署在每个Node上,是一个pod服务,由Kubernetes管理,而不是我们单独部署。

以Ingress Nginx为例(Ingress Controller镜像包含一个Nginx service和一个Ingress Controller)。Ingress Controller会从apiserver获取到Ingress配置,然后动态生成nginx.conf配置文件,并重载(-s reload)配置。

1.3、ingress-nginx工作流程解析

ingress-nginx工作流程 说明
ingress 简单理解:就是你原来需要修改nginx配置,然后配置各种域名对应哪个Service,现在把这个动作抽象出来,变成一个Ingress对象,你可以用yaml创建,每次不用去修改nginx了,直接改yaml然后创建/更新就行了,那么问题又来了:nginx该如何处理呢?
ingress controller ingress controller就是解决nginx如何处理这个问题的,ingress controller通过与kubernetes API交互,动态的去感知集群中Ingress规则变化,然后读取它,按照它自己的模板生成一段nginx配置,再写到nginx Pod中,最后reload以下,工作流程如下图: 1. 首先有一个外部的负载均衡器externalLB把请求调度到一个nodePort类型的Service(ingress-nginx)上; 2. 然后nodePort类型的Service(ingress-nginx)又把它调度到内部的叫做ingressController的Pod上; 3. ingress Ctroller根据ingress中的定义(虚拟主机还是URL),每一组主机名或者URL都对应后端的Pod资源,并且用Service分组。

二、部署ingress-nginx服务

2.1、部署ingress-nginx服务的三种方法

2.1.1、Deployment+LoadBalancer模式的Service

如果要把ingress部署在【公有云】,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个type为LoadBalancer的service关联这组pod。大部分公有云,都会为LoadBalancer的service自动创建一个负载均衡器,通常还绑定了公网地址。只要把域名解析指向该地址,就实现了集群服务的对外暴露。

2.1.2、Deployment+NodePort模式的Service

同样用deployment模式部署ingress-controller,并创建对应的服务,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境,并且IP地址不变的场景。

注意:NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影响。

2.1.3、DaemonSet+HostNetwork+nodeSelector

用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点(如:机房入口的nginx服务器)。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。此方案比较适合大并发的生产环境使用。

2.2、Deployment+NodePort模式使用ingress-nginx

2.2.1、下载并部署ingress资源

首先需要下载ingress相关yaml文件,在nginx controller 0.30.0以及版本之前,需要下载多个yml文件(如:mandatory.yaml、service-nodeport.yaml等)。但在最新nginx controller版本中,这些部署文件合并到一个文件中了,从ingress-nginx/deploy/static/provider/baremetal at main · kubernetes/ingress-nginx · GitHub 下载deploy.yaml文件,这里使用的是最新版本,nginx controller版本为1.15.1,下载后,需要做几个简单修改【即:将registry.k8s.io修改为国内可用的k8s.m.daocloud.io】。

bash 复制代码
#使用DaoCloud代理替换(推荐)
sed -i 's|registry.k8s.io|k8s.m.daocloud.io|g' deploy.yaml

# 或者使用阿里云镜像替换【备选】
sed -i 's|registry.k8s.io/ingress-nginx/controller|registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller|g' deploy.yaml
sed -i 's|registry.k8s.io/ingress-nginx/kube-webhook-certgen|registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen|g' deploy.yaml


#ingress-nginx资源部署
kubectl apply -f deploy.yaml

#查看指定的ingress-nginx的pod资源状态(必须是running;且READY必须是1/1才表示成功)
kubectl -n ingress-nginx get pod

#查看指定的ingress-nginx的pod日志信息
kubectl -n ingress-nginx logs ingress-nginx-controller-5d98f55d49-xtgw4

#查看指定ingress-nginx的所有service
kubectl -n ingress-nginx get svc

#查看指定ingress-nginx的service的详细信息
kubectl -n ingress-nginx describe svc ingress-nginx-controller

2.2.2、配置部署业务服务资源

即需要配置部署业务所需的deployment及其对应的service资源。

k8s容器编排技术实践------k8s对象job应用详解https://blog.csdn.net/xiaochenXIHUA/article/details/161572905

k8s容器编排技术实践------K8s对象deployment应用详解https://coffeemilk.blog.csdn.net/article/details/161427275

k8s容器编排技术实践------k8s对象service应用详解https://coffeemilk.blog.csdn.net/article/details/161593299

bash 复制代码
#创建httpd的pod及其service
#一、创建httpd的deployment资源
#1.1-创建资源文件httpd-deployment.yml
cat > httpd-deployment.yml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
   name: httpd-deployment
spec:
  replicas: 3
  selector:
   matchLabels:
     app: httpd_server
  template:
   metadata:
     labels:
       app: httpd_server
   spec:
    containers:
    - name: httpd-web
      image: library/httpd:2.4.67
      ports:
      - containerPort: 80
EOF
 
 
#1.2-创建指定资源
kubectl apply -f httpd-deployment.yml
 
#1.3查看当前所有pod状态
kubectl get pod



#二、创建对应如上httpd-deployment.yml资源的service
#2.1-创建指定deployment的service资源文件httpd-service.yml
cat >httpd-service.yml<<EOF
apiVersion: v1
kind: Service
metadata:
  name: httpd-service
spec:
 type: NodePort
 selector:
  app: httpd_server
 ports:
 - protocol: TCP
   port: 80
   nodePort: 30060
   targetPort: 80
EOF

#2.2-创建指定的资源文件
kubectl apply -f httpd-service.yml

#2.3-查看当前所有的service
kubectl get svc
bash 复制代码
#创建nginx的pod及其service
#一、创建nginx的deployment资源
#1.1-创建资源文件nginx-deployment.yml
cat > nginx-deployment.yml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
   name: nginx-deployment
spec:
  replicas: 3
  selector:
   matchLabels:
     app: nginx_server
  template:
   metadata:
     labels:
       app: nginx_server
   spec:
    containers:
    - name: nginx-web
      image: library/nginx:1.28.3
      ports:
      - containerPort: 80
EOF
 
 
#1.2-创建指定资源
kubectl apply -f nginx-deployment.yml
 
#1.3查看当前所有pod状态
kubectl get pod -o wide



#二、创建对应如上nginx-deployment.yml资源的service
#2.1-创建指定nginx的service资源文件nginx-service.yml
cat >nginx-service.yml<<EOF
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
 selector:
  app: nginx_server
 ports:
 - protocol: TCP
   port: 80
   targetPort: 80
EOF

#2.2-创建指定的资源文件
kubectl apply -f nginx-service.yml

#2.3-查看当前所有的service
kubectl get svc

#2.4-使用curl连接httpd-service与nginx-service
curl 10.97.0.199
curl 10.104.53.148

2.2.3、创建ingress服务

bash 复制代码
#创建一个ingress服务,让外部可以通过域名来访问pod
cat>ingress-demo.yml<<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-demo
spec:
  ingressClassName: nginx
  rules:
  - host: www.ck.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80
  - host: www.ck1.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: httpd-service
            port:
              number: 80
EOF

#创建指定的资源
kubectl apply -f ingress-demo.yml

#查看ingress-nginx命名空间下的所有Service
kubectl get svc -n ingress-nginx

#配置本地域名解析(即:在本地域名解析文件中添加k8s集群中的任意节点IP 配置的pod域名)
#windows系统的本地域名解析文件是【C:\Windows\System32\drivers\etc\hosts】
#linux系统的本地域名解析文件是【/etc/hosts】
192.168.1.142 www.ck.com
192.168.1.142 www.ck1.com
#或者
192.168.1.140 www.ck.com
192.168.1.140 www.ck1.com
#或者
192.168.1.141 www.ck.com
192.168.1.141 www.ck1.com
#或者
192.168.1.143 www.ck.com
192.168.1.143 www.ck1.com

#浏览器直接访问【域名:ingress-nginx-controller端口】
http://www.ck.com:31992/
http://www.ck1.com:31992/

如上图正确显示不同pod组的service内容,则表示ingress-nginx配置成功!

注意:由于在配置本地域名解析时可以使用k8s集群中的任意节点IP,因此建议在ingress外层再添加一个nginx做负载均衡,这会造成一定的性能损耗。

Nginx中的内置变量、指令、URL重写功能及其虚拟主机配置、负载均衡配置https://blog.csdn.net/xiaochenxihua/article/details/151138716

bash 复制代码
#最终测试完成通过后,删除命令如下
kubectl delete -f ingress-demo.yml
kubectl delete -f deploy.yaml

#查看是否删除完成(显示"No resources found in ingress-nginx namespace."则表示删除完成)
kubectl -n ingress-nginx get pod
kubectl -n ingress-nginx get svc

2.3、DaemonSet+HostNetwork+nodeSelector模式使用ingress-nginx

2.3.1、下载并部署ingress资源

首先需要下载ingress相关yaml文件,在nginx controller 0.30.0以及版本之前,需要下载多个yml文件(如:mandatory.yaml、service-nodeport.yaml等)。但在最新nginx controller版本中,这些部署文件合并到一个文件中了,从ingress-nginx/deploy/static/provider/baremetal at main · kubernetes/ingress-nginx · GitHub 下载deploy.yaml文件,这里使用的是最新版本,nginx controller版本为1.15.1,下载后,需要做几个简单修改【即:将registry.k8s.io修改为国内可用的k8s.m.daocloud.io】。

bash 复制代码
#需要对deploy.yaml文件修改
#1-使用DaoCloud代理替换(推荐)
sed -i 's|registry.k8s.io|k8s.m.daocloud.io|g' deploy.yaml

# 或者使用阿里云镜像替换【备选】
sed -i 's|registry.k8s.io/ingress-nginx/controller|registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller|g' deploy.yaml
sed -i 's|registry.k8s.io/ingress-nginx/kube-webhook-certgen|registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen|g' deploy.yaml

#2-在deployment资源部分,修改名为ingress-nginx-controller的Deployment类型为DaemonSet
kind: DaemonSet

#3-接着在此DaemonSet中的template下的spec中添加如下内容:
#3.1-修改spec下的strategy为updateStrategy

#3.2-这一步配置的操作是【添加网络模式和nodeselector标签,这样ingress-nginx-controller的pod就会部署到特定的node上,并且与宿主机的node网络也打通了,直接使用宿主机的80/433端口就能访问服务】且需要将最后的nodeSelector:kubernetes.io/os: linux注释或者直接修改为ingress: nginx-server。
hostNetwork: true
nodeSelector:
    ingress: nginx-server

#4-给k8s集群中的任意节点(如:k8s-node1)设置ingress标签
kubectl label nodes k8s-node1 ingress=nginx-server

#5-查看当前所有的节点的标签状态
kubectl get node --show-labels



#创建资源
#ingress-nginx资源部署
kubectl apply -f deploy.yaml

#查看指定的ingress-nginx的daemonset资源状态(NODE状态必须是ingress=nginx-server)
kubectl -n ingress-nginx get daemonsets -o wide

#查看指定的ingress-nginx的pod资源状态(必须是running;READY必须是1/1;且IP必须是该节点所在的主机IP(如:192.168.1.142)而不是k8s的内部IP才表示成功)
kubectl -n ingress-nginx get pod -o wide

#查看指定的ingress-nginx的pod日志信息
kubectl -n ingress-nginx logs ingress-nginx-controller-5jzqh

#查看指定ingress-nginx的所有service
kubectl -n ingress-nginx get svc

#查看指定ingress-nginx的service的详细信息
kubectl -n ingress-nginx describe svc ingress-nginx-controller

2.3.2、配置部署业务服务资源

即需要配置部署业务所需的deployment及其对应的service资源。

bash 复制代码
#创建httpd的pod及其service
#一、创建httpd的deployment资源
#1.1-创建资源文件httpd-deployment.yml
cat > httpd-deployment.yml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
   name: httpd-deployment
spec:
  replicas: 3
  selector:
   matchLabels:
     app: httpd_server
  template:
   metadata:
     labels:
       app: httpd_server
   spec:
    containers:
    - name: httpd-web
      image: library/httpd:2.4.67
      ports:
      - containerPort: 80
EOF
 
 
#1.2-创建指定资源
kubectl apply -f httpd-deployment.yml
 
#1.3查看当前所有pod状态
kubectl get pod



#二、创建对应如上httpd-deployment.yml资源的service
#2.1-创建指定deployment的service资源文件httpd-service.yml
cat >httpd-service.yml<<EOF
apiVersion: v1
kind: Service
metadata:
  name: httpd-service
spec:
 type: NodePort
 selector:
  app: httpd_server
 ports:
 - protocol: TCP
   port: 80
   nodePort: 30060
   targetPort: 80
EOF

#2.2-创建指定的资源文件
kubectl apply -f httpd-service.yml

#2.3-查看当前所有的service
kubectl get svc
bash 复制代码
#创建nginx的pod及其service
#一、创建nginx的deployment资源
#1.1-创建资源文件nginx-deployment.yml
cat > nginx-deployment.yml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
   name: nginx-deployment
spec:
  replicas: 3
  selector:
   matchLabels:
     app: nginx_server
  template:
   metadata:
     labels:
       app: nginx_server
   spec:
    containers:
    - name: nginx-web
      image: library/nginx:1.28.3
      ports:
      - containerPort: 80
EOF
 
 
#1.2-创建指定资源
kubectl apply -f nginx-deployment.yml
 
#1.3查看当前所有pod状态
kubectl get pod -o wide



#二、创建对应如上nginx-deployment.yml资源的service
#2.1-创建指定nginx的service资源文件nginx-service.yml
cat >nginx-service.yml<<EOF
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
 selector:
  app: nginx_server
 ports:
 - protocol: TCP
   port: 80
   targetPort: 80
EOF

#2.2-创建指定的资源文件
kubectl apply -f nginx-service.yml

#2.3-查看当前所有的service
kubectl get svc

#2.4-使用curl连接httpd-service与nginx-service
curl 10.97.0.199
curl 10.104.53.148

2.3.3、创建ingress服务

bash 复制代码
#创建一个ingress服务,让外部可以通过域名来访问pod
cat>ingress-demo.yml<<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-demo
spec:
  ingressClassName: nginx
  rules:
  - host: www.ck.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80
  - host: www.ck1.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: httpd-service
            port:
              number: 80
EOF

#创建指定的资源
kubectl apply -f ingress-demo.yml

#查看ingress的状态信息
kubectl get ingress

#查看指定ingress-nginx命名空间下的所有pod状态详情
kubectl -n ingress-nginx get pod -o wide

#查看ingress-nginx命名空间下的所有Service状态
kubectl -n ingress-nginx get svc

#配置本地域名解析(即:在本地域名解析文件中添加指定了标签名称的podIP与域名)
#windows系统的本地域名解析文件是【C:\Windows\System32\drivers\etc\hosts】
#linux系统的本地域名解析文件是【/etc/hosts】
192.168.1.142 www.ck.com
192.168.1.142 www.ck1.com

#浏览器直接访问【域名】
http://www.ck.com
http://www.ck1.com


#剖析《ingress-controller会动态加载ingress服务资源,而不用手动配置》
#1-查看指定ingress-nginx命名空间下的所有pod状态详情
kubectl -n ingress-nginx get pod -o wide

#2-进入ingress-nginx的pod容器中(默认就在/etc/nginx目录下直接查看nginx.conf文件是否包含ingress服务的网站域名配置,有则表示是动态配置上的)
kubectl exec -it -n ingress-nginx ingress-nginx-controller-5jzqh sh

#也就是说需要配置网站域名内容只需要修改ingress服务资源文件后重新创建即可!!!

如上图,通过不同的域名可以正确显示不同pod组的service内容,则表示ingress-nginx配置成功!

相关推荐
张忠琳3 小时前
【client-go v0.36.1】tools/cache 深度分析(中篇)— 辅助组件逐行解析
云原生·kubernetes·cache·informer·client-go
张忠琳8 小时前
【client-go v0.36.1】WorkQueue 深度分析(下篇)— 限流队列、限流器、指标、并行化
云原生·kubernetes·informer·workqueue·client-go
张忠琳10 小时前
【client-go v0.36.1】WorkQueue 深度分析(上篇)— 模块定位、结构、基础队列与延迟队列
云原生·kubernetes·informer·workqueue·client-go
张忠琳10 小时前
【client-go v0.36.1】tools/cache 深度分析(上篇)— 模块定位、整体结构、接口与依赖关系
云原生·kubernetes·cache·informer·client-go
张忠琳10 小时前
【client-go v0.36.1】(Reflector Part 1)Reflector 超深度分析 — 模块定位、整体结构、接口与依赖
云原生·kubernetes·informer·client-go·reflector
张忠琳11 小时前
【client-go v0.36.1】client-go v0.36.1 系统级架构分析(下篇)
云原生·kubernetes·client-go
IT策士11 小时前
第50篇 k8s之系列总结 + 项目演示与后续扩展
云原生·容器·kubernetes
卧室小白11 小时前
K8S-Pod的生命周期与调度
云原生·容器·kubernetes
张忠琳21 小时前
【SR-IOV cni】(Part 4) SR-IOV Network Device Plugin 3.11.0 — 超深度架构分析
网络·云原生·kubernetes·cni·sriov