Linux学习28-Kubernetes service

service简介

Service 主要负责集群内部通讯流量,称之为东西流量(具有 Namespace 隔离性);Service 是 Kubernetes 实现微服务架构的核心概念,通过创建 Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。Service 用于为一组提供服务的 Pod 抽象一个稳定的网络访问地址。

Label 和 Selector

Label(标签)是 Kubernetes 系统中的另一个核心概念,相当于我们熟悉的"标签"。一个 Label 是一个 key=value 键值对,其中的 key 与 value 由用户自己指定。Label 可以被附加到各种资源对象上,例如 Node、 Pod、Service、Deployment 等,一个资源对象可以定义任意数量的 Label,同一个 Label 也可以被添加到任意数量的资源对象上。Label 通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。可以通过给指定的资源对象捆绑一个或多个不同的 Label 来实现多维度的资源分组管理功能,以便灵活、方便地进行资源分配、调度、配置、 部署等管理工作。

Label Selector(标签选择器)查询和筛选拥有某些 Label 的资源对象,Kubernetes 通过这种方式实现了类似 SQL 的简单又通用的对象查询机制。Label Selector 可以被类比为 SQL 语句中的 where 查询条件,例如,"name=redis-slave"这个 Label Selector 作用于 Pod 时,可以被类比 为 select * from pod where name='redis-slave' 这样的语句。当前有两种 Label Selector 表达式:基于等式的(Equality-based)Selector表达式和基于集合的(Set-based)Selector表达式。

  • 等式类表达式

    • name=redis-slave:匹配所有具有 name=redis-slave 标签的资源对象。
    • env != prod:匹配所有不具有 env=prod 标签的资源对象,比如"env=test"就是满足此条件的标签之一。
  • 集合操作类表达式

    • name in (redis-master,redis-slave):匹配所有具有 name=redis-master 标签或者 name=redis-slave 标签的资源对象。
    • name not in (php-frontend):匹配所有不具有 name=php-frontend 标签的资源对象。

示例:

复制代码
# Step 1:查看节点所有的标签`
`$ kubectl get nodes --show-labels`

`# Step 2:查看符合指定标签的节点`
`$ kubectl get nodes -l node-role.kubernetes.io/control-plane=`
`NAME                STATUS   ROLES           AGE    VERSION`
`prod-k8s-master01   Ready    control-plane   6d3h   v1.31.12`
`prod-k8s-master02   Ready    control-plane   6d3h   v1.31.12`
`prod-k8s-master03   Ready    control-plane   6d3h   v1.31.12`

`# Step 3:给指定节点打上标签`
`$ kubectl label  nodes  prod-k8s-master0{1..3}` `role=master`
`node/prod-k8s-master01 labeled`
`node/prod-k8s-master02 la-beled`
`node/prod-k8s-master03 labeled`
`$ kubectl label  nodes  prod-k8s-node0{1..3}` `role=work`
`node/prod-k8s-node01 labeled`
`node/prod-k8s-node02 labeled`
`node/prod-k8s-node03 labeled`

`# Step 3:查看不符合指定标签的节点`
`$ kubectl get nodes -l role!=master`
`NAME              STATUS   ROLES    AGE     VERSION`
`prod-k8s-node01   Ready    <none>   6d4h    v1.31.12`
`prod-k8s-node02   Ready    <none>   6d4h    v1.31.12`
`prod-k8s-node03   Ready    <none>   4d23h   v1.31.12`

`# Step 4:集合方式查看`
`$ kubectl get nodes -l 'role in (master,work)'`
`NAME                STATUS   ROLES           AGE     VERSION`
`prod-k8s-master01   Ready    control-plane   6d4h    v1.31.12`
`prod-k8s-master02   Ready    control-plane   6d4h    v1.31.12`
`prod-k8s-master03   Ready    control-plane   6d4h    v1.31.12`
`prod-k8s-node01     Ready    <none>          6d4h    v1.31.12`
`prod-k8s-node02     Ready    <none>          6d4h    v1.31.12`
`prod-k8s-node03     Ready    <none>          4d23h   v1.31.12`
`$ kubectl get nodes -l 'role notin (master,work)'`

`# Step 5:通过标签key查看`
`kubectl  get nodes -l role`
`NAME                STATUS   ROLES           AGE     VERSION`
`prod-k8s-master01   Ready    control-plane   6d4h    v1.31.12`
`prod-k8s-master02   Ready    control-plane   6d4h    v1.31.12`
`prod-k8s-master03   Ready    control-plane   6d4h    v1.31.12`
`prod-k8s-node01     Ready    <none>          6d4h    v1.31.12`
`prod-k8s-node02     Ready    <none>          6d4h    v1.31.12`
`prod-k8s-node03     Ready    <none>          4d23h   v1.31.12`

`# Step 6:修改标签`
`$ kubectl label node prod-k8s-node01 role=node --overwrite `
`node/prod-k8s-node01 labeled`
`$ kubectl get  nodes -l role=node`
`NAME              STATUS   ROLES    AGE    VERSION`
`prod-k8s-node01   Ready    <none>   6d4h   v1.31.12`

`# Step 7:删除标签`
`$ kubectl label nodes prod-k8s-node01 node-

软件定义型网络

现在常用IPVS

service类型: ClusterIP


创建 ClusterIP service

查看 service-db.yml

kubectl create -f service-db.yml

复制代码
# cat service-db.yml`
`apiVersion:` `"v1"`
`kind:` `"Service"`
`metadata:`
  `name:` `"database-service"`
`spec:`
  `type:` `"ClusterIP"`
  `ports:`
  `-` `protocol:` `"TCP"`
    `port:` `3306`
  `selector:`
    `app:` `"db"`
  `sessionAffinity: ClientIP

检查服务及其端点

kubectl get services -o wide

kubectl get pods -o wide --show-labels

kubectl get endpoints


查看地址转换


重建webserver pod

kubectl delete pod webserver

kubectl create -f pod-web.yml
访问 http://WEBSERVER-POD-IP/cgi-bin/action
可以看到在没有更改数据库连接地址,依然可以访问数据库,为什么?

因为应用程序根本不需要知道数据库真实的 IP 是什么,它只需要连接 Kubernetes 为数据库分配的那个"永远不会变的虚拟 IP(ClusterIP)"即可


使用以下命令探索

kubectl exec -it webserver -- bash

grep connect /var/www/cgi-bin/action

env | grep DATABASE_SERVICE


会发现当service创建之后,pod在重建时会自动配置环境变量

SVCNAME_SERVICE_HOST

SVCNAME_SERVICE_PORT

CoreDNS (KubeDNS/SkyDNS)

  • 通过 Kubernetes 监控服务和端点
  • 管理相关 DNS 资源
    • 创建默认集群 DNS 名称
      • cluster.local
    • 将 DNS 名称分配给命名空间
      • default.svc.cluster.local
    • 为服务分配 DNS 名称
      • database-service.default.svc.cluster.local
      • 创建A类资源记录:ClusterIP

查看kube-dns

kubectl get namespaces

kubectl -n kube-public describe configmap cluster-info

kubectl -n kube-system get svc -o wide

kubectl -n kube-system get po -o wide -l k8s-app=kube-dns

kubectl -n kube-system describe ep kube-dns

检查服务主机名

kubectl exec -it webserver -- bash

ping -c1 database-service

ping -c1 database-service.default

telnet database-service 3306

cat /etc/resolv.conf

最佳实践

在k8s集群中组件之间直接通过服务名称互访

kubectl exec -it webserver -- bash

vi /var/www/cgi-bin/action


重构镜像

查看 /resources/build-dns.sh

复制代码
# cat build-dns.sh`
`#!/bin/bash`

`#export CID=$(docker ps -a | grep webapp | cut -f1 -d ' ')`
`#docker rm -f $CID &>/dev/null`

`export CID=$(docker create reg.westos.org/library/httpd:webapp)`
`#export CID=$(docker ps -a | grep webapp | cut -f1 -d ' ')`

`docker cp /resources/httpd.conf $CID:/etc/httpd/conf/`
`docker cp /resources/run-httpd.sh $CID:/`
`docker cp /resources/action $CID:/var/www/cgi-bin/`

`docker commit $CID reg.westos.org/library/httpd:dns`
`docker push reg.westos.org/library/httpd:dns`

`docker rm $CID`
`


使用查询 DNS 数据库服务的新应用程序创建镜像: /resources/action

con = mdb.connect('database-service', 'root', 'redhat', 'mysql')

复制代码
# cat action`
`#!/usr/bin/python`
`# -*- coding: utf-8 -*-`
`import MySQLdb as mdb`
`import os`

`con = mdb.connect('database-service',` `'root',` `'redhat',` `'mysql')`

`with` `con:`

`    cur = con.cursor()`
`    cur.execute("SELECT User FROM user")`

`    rows = cur.fetchall()`

`    print 'Content-type:text/html\r\n\r\n'`
`    print '<html>'`
`    print '<head>'`
`    print '<title>My Application</title>'`
`    print '</head>'`
`    print '<body>'`
`    print '<h1>'` `+` `'Here comes the list of database users:'` `+` `'</h1>'`


    `for row in` `rows:`
`        print '<h2>'` `+ row[0]` `+` `'</h2>'`

`    print '</body>'`
`    print '</html>'`

`


运行 /resources/build-dns.sh,稍后将使用新创建的应用程序镜像

Kube-proxy 代理模式

在 Kubernetes 中,kube-proxy 负责实现 Service 与 Pod 之间的流量转发,主要支持 iptables 和 IPVS 两种模式。
mode: "" 为空表示默认使用iptables

iptables模式与ipvs模式区别

|------------------------|------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|
| | iptables 模式 | IPVS 模式 |
| 技术基础 | 基于 Linux 内核的 iptables 防火墙规则(属于内核态的包过滤系统)。 | 基于 Linux 内核的 IPVS(IP Virtual Server,专门用于负载均衡的内核模块)。 |
| 转发逻辑 | 通过在 nat 表中添加大量规则(如 KUBE-SERVICE、KUBE-SEP 链),实现 Service 到 Pod 的 DNAT 转发和负载均衡。 | 通过创建虚拟服务(VS)和真实服务器(RS),直接在内核态完成流量调度,规则更简洁(仅记录 Service 与 Pod 的映射关系)。 |
| 规则存储 | 规则以链式结构存储在 iptables 表中,查找时需遍历链条,复杂度随规则数量增加而上升。 | 规则存储在哈希表中,查找效率为 O (1),与规则数量无关。 |
| 大规模集群(Pod 多) | 性能下降明显:当 Service 和 Pod 数量较多时(如数千个),iptables 规则链会变得冗长,遍历规则耗时增加,导致转发延迟升高。 | 性能稳定:IPVS 专为负载均衡设计,哈希表查找效率高,即使集群规模很大(上万 Pod),转发延迟也能保持较低水平。 |
| 流量转发效率 | 较低:iptables 本质是防火墙,转发过程需经过多次规则匹配,额外开销大。 | 较高:IPVS 直接在内核态完成流量调度,路径更短,开销更小(尤其高并发场景下优势明显)。 |
| 负载均衡算法 | 仅支持 随机(random) 和 轮询(round-robin) 两种简单算法。 | 支持 8 种算法,包括:轮询(rr)、加权轮询(wrr)、最少连接(lc)、加权最少连接(wlc)、基于局部性的最少连接(lblc)等,可根据业务场景灵活选择(如对后端负载敏感的服务用 lc 算法)。 |
| 会话保持(Session Affinity) | 支持,但依赖 iptables 的 ip_hash 模块,实现较简单。 | 原生支持更高效的会话保持,通过 persistent 选项实现,性能优于 iptables。 |

切换IPVS模式

修改proxy配置


重启pod


在集群节点上确认是否切换


切换ipvs模式后,kube-proxy会在宿主机上添加一个虚拟网卡:kube-ipvs0,并分配service IP


查看ipvs规则

service类型 NodePort

使用 NodePort 发布 web 服务器

创建 NodePort service


替换 web server Pod

修改 pod-web.yml

使用标签为dns的新镜像

检查端点


查看 NodePort


访问应用程序

nodeport默认端口

cat service-web-np.yml,这里为30000

尝试修改为33333

结果报错,nodeport默认端口是30000-32767,超出会报错


在master节点上修改api-server 的配置

添加如下参数,端口范围可以自定义

  • --service-node-port-range=30000-50000


修改后api-server会自动重启,等apiserver正常启动后才能操作集群

service类型: LoadBalancer

LoadBalancer模式适用云平台,裸金属环境需要安装metallb提供支持

将服务直接关联到ip

metallb

官网:https://metallb.universe.tf/installation/
kube-proxy 需要启用严格ARP模式

重启服务

下载部署文件


下载镜像

harbor新建项目

给 MetalLB 相关的 Docker 镜像重新打标签并推送到私有仓库


安装 MetalLB 控制器

修改部署文件

部署服务


验证部署状态


配置 IP 地址池和Layer 2 模式

使用 LoadBalancer 发布 Web 服务器

cat service-web-lb.yml

apiVersion: "v1"

kind: "Service"

metadata:

name: "web-service-lb"

spec:

allocateLoadBalancerNodePorts: false

type: "LoadBalancer"

ports:

  • name: "http"

protocol: "TCP"

port: 80

targetPort: 80

selector:

app: "web"
注意 MetalLB 分配的 EXTERNAL-IP


查看 LoadBalancer

访问

service类型: externalname

在 Kubernetes 中,ExternalName 是一种特殊类型的 Service,它不通过选择器(selector)关联任何 Pod,而是直接将 Service 映射到一个外部域名(FQDN),用于将集群内部的服务请求转发到集群外部的域名。

核心特点

  • 无选择器:不关联任何 Pod,也不会创建 Endpoints 或 EndpointSlice 资源。
  • 域名映射:通过 externalName 字段指定一个外部域名(如 example.com),Kubernetes 会自动在集群 DNS 中创建一条 CNAME 记录,将 Service 名称解析为该外部域名。
  • 无端口配置:无需指定端口(ports),因为它仅做域名映射,不处理流量转发。

典型用途

  • 访问集群外服务:将外部服务(如第三方 API、数据库)以 Kubernetes Service 的形式暴露给集群内的 Pod,统一服务访问方式。
  • 服务迁移过渡:在将外部服务迁移到集群内的过程中,先通过 ExternalName 指向外部地址,迁移完成后再切换为普通 Service,避免修改应用代码。
  • 简化配置:集群内 Pod 只需使用 Service 名称(如 external-service.default.svc.cluster.local)访问,无需硬编码外部域名,便于统一管理。

创建 ExternalName 类型的 Service

service-externalname.yml

apiVersion: v1

kind: Service

metadata:

name: my-service

spec:

type: ExternalName

externalName: www.baidu.com

测试dns解析

headless服务

在 Kubernetes 中,Headless Service(无头服务) 是一种特殊的 ClusterIP 类型 Service,核心特点是不分配集群虚拟 IP(ClusterIP),而是直接通过 DNS 解析返回其关联的所有 Pod IP 列表,让客户端自主选择 Pod 进行通信。

  • 不分配 ClusterIP:与普通 ClusterIP Service 最大区别,DNS 解析时不会返回单一虚拟 IP。
  • DNS 直接返回 Pod IP:客户端解析 Headless Service 名称时,DNS 会返回所有健康 Pod 的 IP 列表(A/AAAA 记录)。
  • 支持自定义域名:结合 externalName 可实现更灵活的 DNS 配置(较少用)。
  • 依赖 Endpoints/EndpointSlice:需通过 selector 关联 Pod,或手动创建 Endpoints 绑定 IP。

与普通ClusterIP的对比,当前无头服务被使用较多,因为其省去了中间的一层转换,直接找到了端口的port,但同时也失去了负载均衡的能力,之后我们会讲解如何使用无头服务实现负载均衡

"tailless"服务

并不是官方的说法,虽然叫做无尾服务,但在此篇中,实际上使用的是无头无尾(不完整)服务

  • 可以在没有选择器的情况下创建服务,并手动创建端点
  • Kubernetes 应用程序可以通过创建"Tailless"服务连接到现有基础设施

cat service-tailless.yml

apiVersion: "v1"

kind: "Service"

metadata:

name: "tailless"

spec:

clusterIP: None

ports:

  • name: dns

protocol: UDP

port: 53

#请注意,该服务没有选择器

可以看到比起headless没有端点

cat endpointslices-internet.yml

apiVersion: discovery.k8s.io/v1

kind: EndpointSlice

metadata:

name: tailless-1 # 按惯例将 Service 的名称用作 EndpointSlice 名称的前缀

labels:

kubernetes.io/service-name: tailless # 匹配 Service 的名称

addressType: IPv4

ports:

  • name: dns

protocol: UDP

port: 53

endpoints:

  • addresses:

  • "114.114.114.114"


测试

kubectl run -it --rm --image=reg.westos.org/library/busybox:1.30.1 -- sh

If you don't see a command prompt, try pressing enter.

/ # nslookup yahoo.com tailless

Server: tailless

Address: 114.114.114.114:53

Non-authoritative answer:

Name: yahoo.com

Address: 98.137.11.164

Name: yahoo.com

Address: 74.6.143.25

Name: yahoo.com

Address: 74.6.143.26

将端点IP地址更改为 223.5.5.5

kubectl edit endpointslices.discovery.k8s.io tailless-1

测试

kubectl run -it --rm --image=reg.westos.org/library/busybox:1.30.1 -- sh

If you don't see a command prompt, try pressing enter.

/ # nslookup yahoo.com tailless

Server: tailless

Address: 223.5.5.5:53

Non-authoritative answer:

Name: yahoo.com

Address: 74.6.143.26

Name: yahoo.com

Address: 74.6.143.25

Name: yahoo.com

Address: 74.6.231.21

Ingress

Service 的表现形式为 IP 地址和端口号( ClusterIP:Port ),即工作在 TCP/IP 层。而对于基于 HTTP 的服务来说,不同的 URL 地址经常对应到不同的后端服务或者虚拟服务器,这些应用层的转发机制仅通过 Kubernetes 的 Service 机制是无法实现的。

Kubernetes 引入 Ingress 资源对象,用于将 Kubernetes 集群外的客户端请求路由到集群内部的服务上,同时提供 7 层( HTTP 和 HTTPS )路由功能。使用 Ingress 策略定义和一个具体提供转发服务的 Ingress Controller ,两者结合,实现了基于灵活 Ingress 策略定义的服务路由功能。Ingress 只能以 HTTP 和 HTTPS 提供服务,对于使用其他网络协议的服务,可以通过设置 Service 的类型( type )为 NodePort 或LoadBalancer 对集群外部的客户端提供服务。 使用 Ingress 进行服务路由时,Ingress Controller 基于 Ingress 规则将客户端请求直接转发到 Service 对应的后端 Endpoint ( Pod )上。提供负载均衡、SSL 终止和基于名称的虚拟主机,应用的灰度发布等功能。

Ingress Controller

Ingress Controller 需要实现基于不同HTTP URL向后转发的负载分发规则,并可以灵活设置7层负载分发策略。目前 Ingress Controller 已经有许多实现方案,包括 Nginx、HAProxy、Kong、Traefik、Istio 等开源软件的实现,以及公有云GCE、Azure、AWS 等提供的 Ingress 应用网关。

Ingress Controller 会持续监控 API Server 的 /ingress 接口(即用户定义的到后端服务的转发规则)的变化。当 /ingress 接口后端的服务信息发生变化时,Ingress Controller 会自动更新其转发规则。

部署ingress-nginx

官网:https://kubernetes.github.io/ingress-nginx/
下载镜像:

上传镜像


下载部署文件


修改部署文件,镜像位置与私有仓库匹配,一共是三处位置

部署服务


检查资源


可以看到默认使用NodePort方式

Loadbalancer+ingress-nginx部署方式

架构灵活且高可用,但性能有损失。


修改service类型为:LoadBalancer

即刻生效

D aemonSet+hostNetwork 部署方式

链路简单且高效,极致性能。

删除

kubectl delete -f deploy.yaml

修改部署文件

vim deploy.yaml

参数解释:

kind: DaemonSet #使用DaemonSet控制器

updateStrategy #更新策略

hostNetwork: true # 使用主机网络

dnsPolicy: ClusterFirstWithHostNet # 优先集群 DNS(内部域名),再用节点 DNS ,设置 "hostNetwork: true "时是必须要配置的。

nodeSelector: #选择专用节点

添加节点标签

kubectl label node k8s-worker-01 ingress-node="true"

重新部署

kubectl apply -f deploy.yaml

查看pod是否使用主机IP

kubectl -n ingress-nginx get pod -o wide

查看ingressclass

kubectl get ingressclasses.networking.k8s.io

NAME CONTROLLER PARAMETERS AGE

nginx k8s.io/ingress-nginx <none> 13m

基于名称的虚拟主机服务

Ingress 资源的作用 :通过编写 YAML 文件,可以将外部的域名(如 web.example.com)与集群内部的后端 Service(如 web-service:80)进行绑定。

流量调度机制:当外部请求携带特定的域名(Host 头)进入集群时,nginx-ingress-controller 能够根据 Ingress 规则,将流量精准地路由(转发)到对应的后端 Pod 上,从而实现"一个 IP 对应多个不同域名网站"的虚拟主机功能。
创建ingress资源

cat ingress-virtual-host.yml

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: ingress-virtual-host

spec:

ingressClassName: nginx

rules:

http:

paths:

  • path: /

pathType: Prefix

backend:

service:

name: web-service

port:

number: 80

创建后查看资源


测试

域名访问需要在hosts文件中添加解析

还可以进入Ingress Controller的终端,查看,发现与正常的nginx服务基本相同

查看配置文件,与正常配置虚拟ip类似

多域名访问

创建测试服务

cat deploy-web1.yml

apiVersion: "v1"

kind: "Pod"

metadata:

name: "web1"

labels:

app: "web1"

spec:

containers:

  • name: "web1"

image: "reg.westos.org/library/myapp:v1"

ports:

  • containerPort: 80

apiVersion: v1

kind: Service

metadata:

labels:

app: web-v1

name: web-v1

spec:

ports:

  • port: 80

protocol: TCP

targetPort: 80

selector:

app: web1

type: ClusterIP


apiVersion: "v1"

kind: "Pod"

metadata:

name: "web2"

labels:

app: "web2"

spec:

containers:

  • name: "web2"

image: "reg.westos.org/library/myapp:v2"

ports:

  • containerPort: 80

apiVersion: v1

kind: Service

metadata:

labels:

app: web-v2

name: web-v2

spec:

ports:

  • port: 80

protocol: TCP

targetPort: 80

selector:

app: web2

type: ClusterIP

修改ingress资源

拉取myqpp镜像,分别拉取v1,v2

推送到仓库

删除重建使其重新拉取镜像


查看ingress资源

测试

添加解析

或者直接curl该pod的IP

多路径访问


apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: ingress-virtual-path

annotations:

nginx.ingress.kubernetes.io/rewrite-target: /

spec:

ingressClassName: nginx

rules:

http:

paths:

  • path: /v1

pathType: Prefix

backend:

service:

name: web-v1

port:

number: 80

  • path: /v2

pathType: Prefix

backend:

service:

name: web-v2

port:

number: 80

default backend

自定义错误页面

https://kubernetes.github.io/ingress-nginx/examples/customization/custom-errors/

apiVersion: v1

kind: Service

metadata:

name: nginx-errors

labels:

app.kubernetes.io/name: nginx-errors

app.kubernetes.io/part-of: ingress-nginx

spec:

selector:

app.kubernetes.io/name: nginx-errors

app.kubernetes.io/part-of: ingress-nginx

ports:

  • port: 80

targetPort: 8080

name: http


apiVersion: v1

kind: ConfigMap

metadata:

name: custom-error-pages

data:

404: |

<!DOCTYPE html>

<html>

<head><title>PAGE NOT FOUND</title></head>

<body>PAGE NOT FOUND</body>

</html>

503: |

<!DOCTYPE html>

<html>

<head><title>CUSTOM SERVICE UNAVAILABLE</title></head>

<body>CUSTOM SERVICE UNAVAILABLE</body>

</html>


apiVersion: apps/v1

kind: Deployment

metadata:

name: nginx-errors

labels:

app.kubernetes.io/name: nginx-errors

app.kubernetes.io/part-of: ingress-nginx

spec:

replicas: 1

selector:

matchLabels:

app.kubernetes.io/name: nginx-errors

app.kubernetes.io/part-of: ingress-nginx

template:

metadata:

labels:

app.kubernetes.io/name: nginx-errors

app.kubernetes.io/part-of: ingress-nginx

spec:

containers:

  • name: nginx-error-server

image: reg.westos.org/ingress-nginx/custom-error-pages:v1.2.4

ports:

  • containerPort: 8080

Setting the environment variable DEBUG we can see the headers sent

by the ingress controller to the backend in the client response.

env:

  • name: DEBUG

value: "true"

Mounting custom error page from configMap

volumeMounts:

  • name: custom-error-pages

mountPath: /www

Mounting custom error page from configMap

volumes:

  • name: custom-error-pages

configMap:

name: custom-error-pages

items:

  • key: "404"

path: "404.html"

  • key: "503"

path: "503.html"

需要拉取镜像

打标签推送


创建资源

查看资源


修改ingress-nginx-controller的DS控制器配置


添加以下行

  • --default-backend-service=ingress-nginx/nginx-errors

严格按照 namespace/servicename 的方式指定

测试

TLS termination

创建证书

查看secret


创建ingress资源
除之前的资源不然会冲突


apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: ingress-web-tls

spec:

tls:

secretName: tls-secret

ingressClassName: nginx

rules:

http:

paths:

  • path: /

pathType: Prefix

backend:

service:

name: web-v1

port:

number: 80

http:

paths:

  • path: /

pathType: Prefix

backend:

service:

name: web-v2

port:

number: 80

查看

添加解析

强制重定向80到443

认证访问

创建认证文件

输入密码不可见


创建ingress

cat ingress-web-tls-auth.yml

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: ingress-web-tls-auth

annotations:

nginx.ingress.kubernetes.io/auth-type: basic

nginx.ingress.kubernetes.io/auth-secret: basic-auth

nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - ljx'

spec:

tls:

secretName: tls-secret

ingressClassName: nginx

rules:

http:

paths:

  • path: /

pathType: Prefix

backend:

service:

name: web-v1

port:

number: 80

http:

paths:

  • path: /

pathType: Prefix

backend:

service:

name: web-v2

port:

number: 80

查看

测试

rewrite重定向

基于路径重定向

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: ingress-rewrite-1

annotations:

nginx.ingress.kubernetes.io/auth-type: basic

nginx.ingress.kubernetes.io/auth-secret: basic-auth

nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - ljx'

nginx.ingress.kubernetes.io/app-root: /cgi-bin/action

spec:

tls:

secretName: tls-secret

ingressClassName: nginx

rules:

http:

paths:

  • path: /

pathType: Prefix

backend:

service:

name: web-service

port:

number: 80

查看

测试,注意最后的地址

基于正则表达式重定向

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: ingress-rewrite-2

annotations:

nginx.ingress.kubernetes.io/auth-type: basic

nginx.ingress.kubernetes.io/auth-secret: basic-auth

nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - ljx'

nginx.ingress.kubernetes.io/use-regex: "true"

nginx.ingress.kubernetes.io/rewrite-target: /$2

spec:

tls:

secretName: tls-secret

ingressClassName: nginx

rules:

http:

paths:

  • path: /testing(/|$)(.*)

pathType: ImplementationSpecific

backend:

service:

name: web-service

port:

number: 80

回收之前的路径重定向,创建

查看

测试

canary金丝雀发布

金丝雀发布的思想则是将少量的请求引流到新版本上,因此部署新版本服务只需极小数的机器。验证新版本符合预期后,逐步调整流量权重比例,使得流量慢慢从老版本迁移至新版本,期间可以根据设置的流量比例,对新版本服务进行扩容,同时对老版本服务进行缩容,使得底层资源得到最大化利用。

• 优点:按比例将流量无差别地导向新版本,新版本故障影响范围小; 发布期间逐步对新版本扩容,同时对老版本缩容,资源利用率高。

• 缺点:流量无差别地导向新版本,可能会影响重要用户的体验;发布周期长。

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: ingress-canary-v1

spec:

ingressClassName: nginx

rules:

http:

paths:

  • pathType: Prefix

path: /

backend:

service:

name: web-v1

port:

number: 80

先回收之前的ingress,否则会冲突

查看

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: ingress-canary-v2

annotations:

nginx.ingress.kubernetes.io/canary: "true"

nginx.ingress.kubernetes.io/canary-weight: "10"

nginx.ingress.kubernetes.io/canary-weight-total: "100"

spec:

ingressClassName: nginx

rules:

http:

paths:

  • pathType: Prefix

path: /

backend:

service:

name: web-v2

port:

number: 80

创建,查看


编写测试脚本

#!/bin/bash

v1=0

v2=0

for (( i=0; i<100; i++))

do

response=`curl -s myapp.example.com |grep -c v1` # 域名需要解析

v1=`expr v1 + response`

v2=`expr v2 + 1 - response`

done

echo "v1:v1, v2:v2"

集群外部测试

A/B测试

A/B 测试基于用户请求的元信息将流量路由到新版本,这是一种基于请求内容匹配的灰度发布策略。只有匹配特定规则的请求才会被引流到新版本,常见的做法包括基于 Http Header 和 Cookie。

基于 Header 的流量切分

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: ingress-ab-header

annotations:

nginx.ingress.kubernetes.io/canary: "true"

nginx.ingress.kubernetes.io/canary-by-header: stage

nginx.ingress.kubernetes.io/canary-by-header-value: gray

spec:

ingressClassName: nginx

rules:

http:

paths:

  • pathType: Prefix

path: /

backend:

service:

name: web-v2

port:

number: 80

测试

基于Cookie的流量切分

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-ab-cookie
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "user_from_sz"
spec:
ingressClassName: nginx
rules:

  • host: myapp.example.com
    http:
    paths:
  • pathType: Prefix
    path: /
    backend:
    service:
    name: web-v2
    port:
    number: 80

测试

相关推荐
传奇开心果编程1 小时前
【xilem0.4基础语法学与练】第45课 xilem_core
学习·rust·前端框架
有梦想的咕噜1 小时前
Newtonsoft.Json (Json.NET) 常用方法汇总
linux·json·.net
码农小韩1 小时前
Linux应用开发(五)——线程
linux·操作系统·linux驱动·嵌入式软件开发·嵌入式操作系统·linux应用
Polevne1 小时前
C# GRPC 一元与双向流
linux·算法·c#
拂拉氏1 小时前
【知识讲解】 Linux程序替换相关接口讲解
linux·程序替换
那年窗外下的雪.2 小时前
AIDC 学习日志|第 25 天|设备输出反推、MAC Flapping 与 EAD 撤销
前端·网络·git·学习·macos
星源~2 小时前
zephyr-Linux环境下搭建步骤
linux·mcu·嵌入式开发·zephyr
Huangjin007_2 小时前
【Linux 系统篇(二十)】进程(八):进程创建、进程退出
linux·运维·服务器
海宇数据2 小时前
零信任架构实战:基于海宇对外投资历史查询服务构建自动化异动企业筛查网关
运维·人工智能·架构·自动化