实验集合:
一.创建一个clusterIP微服务
[root@master services]# kubectl create deployment webcluster --image myapp:v1 --replicas 2 --dry-run=client -o yaml > clusterIP.yml
[root@master services]# kubectl apply -f clusterIP.yml
[root@master services]# kubectl expose deployment webcluster --port 80 --target-port 80 --dry-run=client -o yaml >> clusterIP.yml
[root@master services]# vim clusterIP.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webcluster
name: webcluster
spec:
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
- image: myapp:v1
name: myapp
---
apiVersion: v1
kind: Service
metadata:
labels:
app: webcluster
name: webcluster
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: webcluster
type: ClusterIP
[root@master services]# kubectl apply -f clusterIP.yml
#检控官效果
[root@master ~]# watch -n 1 " kubectl get pods -o wide ; kubectl describe svc webcluster "
Every 1.0s: kubectl get pods -o wide ; kubectl describe svc webcluster master: Sat Apr 11 16:41:55 2026
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS
GATES
webcluster-77c87d9946-bxtlz 1/1 Running 0 56s 10.244.1.47 node1 <none> <none>
webcluster-77c87d9946-ppqc5 1/1 Running 0 56s 10.244.2.39 node2 <none> <none>
Name: webcluster
Namespace: default
Labels: app=webcluster
Annotations: <none>
Selector: app=webcluster
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.105.28.64
IPs: 10.105.28.64
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.47:80,10.244.2.39:80
Session Affinity: None
Internal Traffic Policy: Cluster
Events: <none>
[root@master services]# curl 10.105.28.64/hostname.html
webcluster-77c87d9946-bxtlz
[root@master services]# curl 10.105.28.64/hostname.html
webcluster-77c87d9946-ppqc5
#测试
[root@master services]# kubectl delete pods webcluster-77c87d9946-bxtlz
[root@master services]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
webcluster-77c87d9946-4s2qc 1/1 Running 0 62s app=webcluster,pod-template-hash=77c87d9946
webcluster-77c87d9946-ks5rz 1/1 Running 0 39s app=webcluster,pod-template-hash=77c87d9946
[root@master services]# kubectl label pods webcluster-77c87d9946-4s2qc app-
pod/webcluster-77c87d9946-4s2qc unlabeled
[root@master services]# kubectl label pods webcluster-77c87d9946-4s2qc app=webcluster
pod/webcluster-77c87d9946-4s2qc labeled
二.优化service工作模式
[root@master services]# dnf install ipvsadm -y
[root@master services]# kubectl -n kube-system edit cm kube-prox
59 mode: "ipvs"
[root@master services]# kubectl -n kube-system get pods
NAME READY STATUS RESTARTS AGE
coredns-697886855d-d6kwd 1/1 Running 2 (23h ago) 13d
coredns-697886855d-k92r9 1/1 Running 2 (23h ago) 13d
etcd-master 1/1 Running 2 (23h ago) 13d
kube-apiserver-master 1/1 Running 2 (23h ago) 13d
kube-controller-manager-master 1/1 Running 2 (23h ago) 13d
kube-proxy-7qr9n 1/1 Running 2 (23h ago) 13d
kube-proxy-8sm6w 1/1 Running 2 (23h ago) 13d
kube-proxy-q8q55 1/1 Running 2 (23h ago) 13d
kube-scheduler-master 1/1 Running 2 (23h ago) 13d
[root@master services]# kubectl -n kube-system delete pods kube-proxy-7qr9n
pod "kube-proxy-7qr9n" deleted from kube-system namespace
[root@master services]# kubectl -n kube-system delete pods kube-proxy-8sm6w
pod "kube-proxy-8sm6w" deleted from kube-system namespace
[root@master services]# kubectl -n kube-system delete pods kube-proxy-q8q55
pod "kube-proxy-q8q55" deleted from kube-system namespace
#测试
[root@master ~]# watch -n 1 ipvsadm -Ln
[root@master services]# vim clusterIP.yml
replicas: 2
[root@master services]# kubectl apply -f clusterIP.yml
#查看lvs的轮询列表中的信息即可
三.微服务解析
[root@master ~]# kubectl -n kube-system get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 14d
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
webcluster ClusterIP 10.99.217.241 <none> 80/TCP 17h
[root@master ~]# dig webcluster.default.svc.cluster.local @10.96.0.10
; <<>> DiG 9.16.23-RH <<>> webcluster.default.svc.cluster.local @10.96.0.10
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6731
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: e7905dbdbb637f4a (echoed)
;; QUESTION SECTION:
;webcluster.default.svc.cluster.local. IN A
;; ANSWER SECTION:
webcluster.default.svc.cluster.local. 30 IN A 10.99.217.241
;; Query time: 2 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Sun Apr 12 09:58:53 CST 2026
;; MSG SIZE rcvd: 129
四.clusterIP中的无头服务headless
[root@master services]# kubectl delete -f clusterIP.yml
[root@master services]# vim clusterIP.yml
。。。。。
apiVersion: v1
kind: Service
metadata:
labels:
app: webcluster
name: webcluster
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: webcluster
type: ClusterIP
clusterIP: None #指定此service使用headless模式
[root@master services]# kubectl apply -f clusterIP.yml
deployment.apps/webcluster created
service/webcluster created
[root@master services]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
webcluster ClusterIP None <none> 80/TCP 20s
#测试
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test 1/1 Running 0 112s 10.244.1.53 node1 <none> <none>
webcluster-77c87d9946-rps74 1/1 Running 0 4m4s 10.244.1.51 node1 <none> <none>
webcluster-77c87d9946-vnrw9 1/1 Running 0 4m4s 10.244.2.42 node2 <none> <none>
[root@master services]# dig webcluster.default.svc.cluster.local @10.96.0.10
; <<>> DiG 9.16.23-RH <<>> webcluster.default.svc.cluster.local @10.96.0.10
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28846
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 9b9afd2328a52dfc (echoed)
;; QUESTION SECTION:
;webcluster.default.svc.cluster.local. IN A
;; ANSWER SECTION:
webcluster.default.svc.cluster.local. 30 IN A 10.244.2.42
webcluster.default.svc.cluster.local. 30 IN A 10.244.1.51
;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Sun Apr 12 10:14:03 CST 2026
;; MSG SIZE rcvd: 181
五.nodeport
1.nodeport的建立
[root@master services]# kubectl delete -f clusterIP.yml
deployment.apps "webcluster" deleted from default namespace
service "webcluster" deleted from default namespace
[root@master services]# cp clusterIP.yml nodeport.yml
[root@master services]# vim nodeport.yml
---
apiVersion: v1
kind: Service
metadata:
labels:
app: webcluster
name: webcluster
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: webcluster
type: NodePort #改变类型
[root@master services]# kubectl apply -f nodeport.yml
deployment.apps/webcluster created
service/webcluster created
[root@master services]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
webcluster NodePort 10.96.25.134 <none> 80:31670/TCP 5s
[root@master services]# curl 172.25.254.100:31670/hostname.html
webcluster-77c87d9946-s24sf
[root@master services]# curl 172.25.254.100:31670/hostname.html
webcluster-77c87d9946-62bsl
[root@master services]# curl 172.25.254.100:31670/hostname.html
webcluster-77c87d9946-s24sf
[root@master services]# curl 172.25.254.100:31670/hostname.html
webcluster-77c87d9946-62bsl
2.nodeport端口管理(默认范围30000~32767)
[root@master services]# kubectl delete -f nodeport.yml
deployment.apps "webcluster" deleted from default namespace
service "webcluster" deleted from default namespace
[root@master services]# vim nodeport.yml #在范围之内设定
---
apiVersion: v1
kind: Service
metadata:
labels:
app: webcluster
name: webcluster
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 31111 #设定端口
selector:
app: webcluster
type: NodePort
[root@master services]# kubectl apply -f nodeport.yml
deployment.apps/webcluster created
service/webcluster created
[root@master services]# kubectl get svc webcluster
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
webcluster NodePort 10.108.146.142 <none> 80:31111/TCP 8s
[root@master services]# kubectl delete -f nodeport.yml
deployment.apps "webcluster" deleted from default namespace
service "webcluster" deleted from default namespace
[root@master services]# vim nodeport.yml #在范围外内设定
---
apiVersion: v1
kind: Service
metadata:
labels:
app: webcluster
name: webcluster
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 33333 #设定端口
selector:
app: webcluster
type: NodePort
[root@master services]# kubectl apply -f nodeport.yml
deployment.apps/webcluster created
The Service "webcluster" is invalid: spec.ports[0].nodePort: Invalid value: 33333: provided port is not in the valid range. The range of valid ports is 30000-32767
#解锁默认端口范围
[root@master services]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
42 - --service-node-port-range=30000-40000
#上述文件修改后集群会自动重启,等待120秒左右看集群状态
[root@master services]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane 14d v1.35.3
node1 Ready <none> 14d v1.35.3
node2 Ready <none> 14d v1.35.3
[root@master services]# kubectl apply -f nodeport.yml
deployment.apps/webcluster unchanged
service/webcluster created
[root@master services]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
webcluster NodePort 10.104.45.175 <none> 80:33333/TCP 6s
六.loadbalancer
1.创建loadbalancer
[root@master services]# kubectl delete -f nodeport.yml
deployment.apps "webcluster" deleted from default namespace
service "webcluster" deleted from default namespace
[root@master services]# cp nodeport.yml loadbalance.yml
[root@master services]# vim loadbalance.yml
---
apiVersion: v1
kind: Service
metadata:
labels:
app: webcluster
name: webcluster
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: webcluster
type: LoadBalancer #指定services模式
[root@master services]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
webcluster LoadBalancer 10.109.27.140 <pending> 80:33804/TCP 7s
[root@master services]# curl 172.25.254.100:33804
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master services]# curl 10.109.27.140
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master services]# kubectl edit configmap -n kube-system kube-proxy
40 ipvs:
41 excludeCIDRs: null
42 minSyncPeriod: 0s
43 scheduler: ""
44 strictARP: true #arp响应禁止
[root@master services]# kubectl -n kube-system get pods
NAME READY STATUS RESTARTS AGE
coredns-697886855d-d6kwd 1/1 Running 2 (41h ago) 14d
coredns-697886855d-k92r9 1/1 Running 2 (41h ago) 14d
etcd-master 1/1 Running 2 (41h ago) 14d
kube-apiserver-master 1/1 Running 0 30m
kube-controller-manager-master 1/1 Running 3 (30m ago) 14d
kube-proxy-52zdz 1/1 Running 0 18h #删掉
kube-proxy-5t7vl 1/1 Running 0 18h #删掉
kube-proxy-8s6vj 1/1 Running 0 18h #删掉
kube-scheduler-master 1/1 Running 3 (30m ago) 14d
[root@master services]# kubectl -n kube-system delete pods kube-proxy-52zdz
pod "kube-proxy-52zdz" deleted from kube-system namespace
[root@master services]# kubectl -n kube-system delete pods kube-proxy-5t7vl
pod "kube-proxy-5t7vl" deleted from kube-system namespace
[root@master services]# kubectl -n kube-system delete pods kube-proxy-8s6vj
pod "kube-proxy-8s6vj" deleted from kube-system namespace
#下载metallb的yml文件
[root@master services]# wget https://raw.githubusercontent.com/metallb/metallb/v0.15.3/config/manifests/metallb-native.yaml
[root@master ~]# docker pull quay.io/metallb/controller:v0.15.3
[root@master ~]# docker pull quay.io/metallb/speaker:v0.15.3
[root@master ~]# docker tag quay.io/metallb/controller:v0.15.3 reg.timinglee.org/metallb/controller:v0.15.3
[root@master ~]# docker push reg.timinglee.org/metallb/controller:v0.15.3
[root@master ~]# docker tag quay.io/metallb/speaker:v0.15.3 reg.timinglee.org/metallb/speaker:v0.15.3
[root@master ~]# docker push reg.timinglee.org/metallb/speaker:v0.15.3
[root@master services]# grep -n image: metallb-native.yaml #修改文件下述两行内容
2001: image: metallb/controller:v0.15.3
2098: image: metallb/speaker:v0.15.3
#安装
[root@master services]# kubectl apply -f metallb-native.yaml
[root@master services]# kubectl -n metallb-system get all
NAME READY STATUS RESTARTS AGE
pod/controller-5fbf6546f9-9568r 1/1 Running 0 52s
pod/speaker-976v8 1/1 Running 0 52s
pod/speaker-nm898 1/1 Running 0 52s
pod/speaker-x68v4 1/1 Running 0 52s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/metallb-webhook-service ClusterIP 10.100.120.24 <none> 443/TCP 52s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/speaker 3 3 3 3 3 kubernetes.io/os=linux 52s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/controller 1/1 1 1 52s
NAME DESIRED CURRENT READY AGE
replicaset.apps/controller-5fbf6546f9 1 1 1 52s
#配置metallb
[root@master services]# vim configmap.yml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 172.25.254.50-172.25.254.80
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
[root@master services]# kubectl apply -f configmap.yml
ipaddresspool.metallb.io/first-pool created
l2advertisement.metallb.io/example created
[root@master services]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
webcluster LoadBalancer 10.109.27.140 172.25.254.50 80:33804/TCP 24m
[root@master services]# curl 172.25.254.50
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master services]# curl 172.25.254.50
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master services]# curl 172.25.254.50
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master services]# curl 172.25.254.50
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master services]# curl 172.25.254.50
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
七.externalname
[root@master services]# vim externalname.yml
apiVersion: v1
kind: Service
metadata:
labels:
app: webcluster
name: webcluster
spec:
selector:
app: webcluster
type: ExternalName
externalName: www.baidu.com
[root@master services]# dig webcluster.default.svc.cluster.local @10.96.0.10
; <<>> DiG 9.16.23-RH <<>> webcluster.default.svc.cluster.local @10.96.0.10
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21915
;; flags: qr aa rd; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 631489b7b37a6594 (echoed)
;; QUESTION SECTION:
;webcluster.default.svc.cluster.local. IN A
;; ANSWER SECTION:
webcluster.default.svc.cluster.local. 30 IN CNAME www.baidu.com.
www.baidu.com. 30 IN CNAME www.a.shifen.com.
www.a.shifen.com. 30 IN A 183.2.172.17
www.a.shifen.com. 30 IN A 183.2.172.177
;; Query time: 36 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Sun Apr 12 14:09:30 CST 2026
;; MSG SIZE rcvd: 247
八.ingress-nginx
1.安装
[root@master services]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.15.1/deploy/static/provider/baremetal/deploy.yaml
[root@master services]# vim deploy.yaml
444: image: ingress-nginx/controller:v1.15.1
547: image: ingress-nginx/kube-webhook-certgen:v1.6.9
603: image: ingress-nginx/kube-webhook-certgen:v1.6.9
[root@master ~]# docker load -i ingress-nginx-1.15.1.tar
#上传所有ingres所需镜像到harbor仓库的ingress-nginx项目
[root@master services]# kubectl apply -f deploy-1.15.1.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
root@master services]# kubectl -n ingress-nginx edit svc ingress-nginx-controller
49 type: LoadBalancer、
[root@master services]# kubectl -n ingress-nginx get all
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-controller-6bcbfdbd4b-rf9zm 1/1 Running 0 2m44s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller LoadBalancer 10.103.58.119 172.25.254.50 80:32683/TCP,443:32543/TCP 2m44s
service/ingress-nginx-controller-admission ClusterIP 10.107.149.85 <none> 443/TCP 2m44s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 2m44s
NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-nginx-controller-6bcbfdbd4b 1 1 1 2m44s
[root@master services]# kubectl get ingressclasses.networking.k8s.io
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 4m10s
2.首个ingress
准备2个又明显区分的svc和控制器
[root@master services]# vim myapp1.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: myapp1
name: myapp1
spec:
replicas: 1
selector:
matchLabels:
app: myapp1
template:
metadata:
labels:
app: myapp1
spec:
containers:
- image: myapp:v1
name: myapp
---
apiVersion: v1
kind: Service
metadata:
labels:
app: myapp1
name: myapp1
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: myapp1
type: ClusterIP
[root@master services]# vim myapp2.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: myapp2
name: myapp2
spec:
replicas: 1
selector:
matchLabels:
app: myapp2
template:
metadata:
labels:
app: myapp2
spec:
containers:
- image: myapp:v2
name: myapp
---
apiVersion: v1
kind: Service
metadata:
labels:
app: myapp2
name: myapp2
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: myapp2
type: ClusterIP
[root@master services]# kubectl apply -f myapp1.yml
[root@master services]# kubectl apply -f myapp2.yml、
[root@master services]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
myapp1 ClusterIP 10.101.12.140 <none> 80/TCP 3m41s
myapp2 ClusterIP 10.107.83.65 <none> 80/TCP 104s
创建ingress代理
[root@master services]# kubectl create ingress webcluster --rule='*/=myapp1:80' --dry-run=client -o yaml > 1-ingress.yml
[root@master services]# vim 1-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webcluster
spec:
ingressClassName: nginx
rules:
- http:
paths:
- backend:
service:
name: myapp1
port:
number: 80
path: /
pathType: Prefix
[root@master services]# kubectl -n ingress-nginx get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.103.58.119 172.25.254.50 80:32683/TCP,443:32543/TCP 21m
ingress-nginx-controller-admission ClusterIP 10.107.149.85 <none> 443/TCP 21m
[root@master services]# curl 172.25.254.50
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
3.基于域名的ingress
[root@master services]# vim 2-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
name: webcluster
spec:
ingressClassName: nginx
rules:
- host: myapp1.timinglee.org
http:
paths:
- backend:
service:
name: myapp1
port:
number: 80
path: /
pathType: Prefix
- host: myapp2.timinglee.org
http:
paths:
- backend:
service:
name: myapp2
port:
number: 80
path: /
pathType: Prefix
[root@master services]# kubectl describe ingress webcluster
Name: webcluster
Labels: <none>
Namespace: default
Address:
Ingress Class: nginx
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
myapp1.timinglee.org
/ myapp1:80 (10.244.1.60:80)
myapp2.timinglee.org
/ myapp2:80 (10.244.2.50:80)
Annotations: nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 15s nginx-ingress-controller Scheduled for sync
#测试:
[root@master services]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.100 master
172.25.254.10 node1
172.25.254.20 node2
172.25.254.30 node3
172.25.254.200 reg.timinglee.org
172.25.254.50 myapp1.timinglee.org myapp2.timinglee.org
[root@master services]# curl myapp1.timinglee.org
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master services]# curl myapp2.timinglee.org
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
4.建立tls加密
[root@master services]# openssl req -newkey rsa:2048 -nodes -keyout tls.key -x509 -days 365 -subj "/CN=nginxsvc/O=nginxsvc" -out tls.crt
[root@master services]# kubectl create secret tls web-tls-secret --key tls.key --cert tls.crt
[root@master services]# kubectl get secrets
NAME TYPE DATA AGE
web-tls-secret kubernetes.io/tls 2 3m7s
[root@master services]# vim 3-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
name: webcluster
spec:
tls:
- hosts:
- myapp1.timinglee.org
secretName: web-tls-secret
ingressClassName: nginx
rules:
- host: myapp1.timinglee.org
http:
paths:
- backend:
service:
name: myapp1
port:
number: 80
path: /
pathType: Prefix
[root@master services]# kubectl apply -f 3-ingress.yml
ingress.networking.k8s.io/webcluster created
[root@master services]# kubectl describe ingress
Name: webcluster
Labels: <none>
Namespace: default
Address: 172.25.254.20
Ingress Class: nginx
Default backend: <default>
TLS:
web-tls-secret terminates myapp1.timinglee.org
Rules:
Host Path Backends
---- ---- --------
myapp1.timinglee.org
/ myapp1:80 (10.244.1.60:80)
Annotations: nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 5s (x2 over 15s) nginx-ingress-controller Scheduled for sync
#访问测试
[root@master services]# curl -k https://myapp1.timinglee.org
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
5.建立auth认证
[root@master services]# dnf install httpd-tools -y
[root@master services]# htpasswd -cm auth lee
New password:
Re-type new password:
Adding password for user lee
[root@master services]# cat auth
lee:$apr1$hNTmKmxS$qyM7y53AAzPaIUyCNJcgy.
[root@master services]# kubectl get secrets auth-web -o yaml
apiVersion: v1
data:
auth: bGVlOiRhcHIxJGhOVG1LbXhTJHF5TTd5NTNBQXpQYUlVeUNOSmNneS4K
kind: Secret
metadata:
creationTimestamp: "2026-04-12T08:00:40Z"
name: auth-web
namespace: default
resourceVersion: "163922"
uid: e28c67f8-5465-4ef2-a076-e205bcaf6887
type: Opaque
[root@master services]# echo "bGVlOiRhcHIxJGhOVG1LbXhTJHF5TTd5NTNBQXpQYUlVeUNOSmNneS4K" | base64 -d
lee:$apr1$hNTmKmxS$qyM7y53AAzPaIUyCNJcgy.
[root@master services]# cat auth
lee:$apr1$hNTmKmxS$qyM7y53AAzPaIUyCNJcgy.
[root@master services]# vim 4-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: auth-web
nginx.ingress.kubernetes.io/auth-realm: "Please input username and password"
nginx.ingress.kubernetes.io/rewrite-target: /
name: webcluster
spec:
tls:
- hosts:
- myapp1.timinglee.org
secretName: web-tls-secret
ingressClassName: nginx
rules:
- host: myapp1.timinglee.org
http:
paths:
- backend:
service:
name: myapp1
port:
number: 80
path: /
pathType: Prefix
[root@master services]# kubectl apply -f 4-ingress.yml
ingress.networking.k8s.io/webcluster created
#测试:
[root@master services]# kubectl describe ingress
Name: webcluster
Labels: <none>
Namespace: default
Address: 172.25.254.20
Ingress Class: nginx
Default backend: <default>
TLS:
web-tls-secret terminates myapp1.timinglee.org
Rules:
Host Path Backends
---- ---- --------
myapp1.timinglee.org
/ myapp1:80 (10.244.1.60:80)
Annotations: nginx.ingress.kubernetes.io/auth-realm: Please input username and password
nginx.ingress.kubernetes.io/auth-secret: auth-web
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 2s (x2 over 17s) nginx-ingress-controller Scheduled for sync
[root@master services]# curl -k https://myapp1.timinglee.org
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx</center>
</body>
</html>
[root@master services]# curl -k https://myapp1.timinglee.org -u lee:lee
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
6.网页重写
示例1
[root@master services]# vim 5-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/app-root: /hostname.html #设定默认测试也
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: auth-web
nginx.ingress.kubernetes.io/auth-realm: "Please input username and password"
nginx.ingress.kubernetes.io/rewrite-target: /
name: webcluster
spec:
tls:
- hosts:
- myapp1.timinglee.org
secretName: web-tls-secret
ingressClassName: nginx
rules:
- host: myapp1.timinglee.org
http:
paths:
- backend:
service:
name: myapp1
port:
number: 80
path: /
pathType: Prefix
[root@master services]# kubectl apply -f 5-ingress.yml
ingress.networking.k8s.io/webcluster created
[root@master services]# kubectl describe ingress webcluster
Name: webcluster
Labels: <none>
Namespace: default
Address:
Ingress Class: nginx
Default backend: <default>
TLS:
web-tls-secret terminates myapp1.timinglee.org
Rules:
Host Path Backends
---- ---- --------
myapp1.timinglee.org
/ myapp1:80 (10.244.1.60:80)
Annotations: nginx.ingress.kubernetes.io/app-root: /hostname.html
nginx.ingress.kubernetes.io/auth-realm: Please input username and password
nginx.ingress.kubernetes.io/auth-secret: auth-web
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 12s nginx-ingress-controller Scheduled for sync
#测试:
[root@master services]# curl -lk https://myapp1.timinglee.org -u lee:lee
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
[root@master services]# curl -Lk https://myapp1.timinglee.org -u lee:lee
myapp1-8456b584d6-7g4lq
示例2
[root@master services]# vim 5-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: auth-web
nginx.ingress.kubernetes.io/auth-realm: "Please input username and password"
nginx.ingress.kubernetes.io/rewrite-target: /
name: webcluster
spec:
tls:
- hosts:
- myapp1.timinglee.org
secretName: web-tls-secret
ingressClassName: nginx
rules:
- host: myapp1.timinglee.org
http:
paths:
- backend:
service:
name: myapp1
port:
number: 80
path: /lee(/|$)(.*)
pathType: ImplementationSpecific
[root@master services]# kubectl apply -f 5-ingress.yml
ingress.networking.k8s.io/webcluster created
[root@master services]# kubectl describe ingress webcluster
Name: webcluster
Labels: <none>
Namespace: default
Address:
Ingress Class: nginx
Default backend: <default>
TLS:
web-tls-secret terminates myapp1.timinglee.org
Rules:
Host Path Backends
---- ---- --------
myapp1.timinglee.org
/lee(/|$)(.*) myapp1:80 (10.244.1.60:80)
Annotations: nginx.ingress.kubernetes.io/auth-realm: Please input username and password
nginx.ingress.kubernetes.io/auth-secret: auth-web
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/use-regex: true
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 13s nginx-ingress-controller Scheduled for sync
[root@master services]# curl -Lk https://myapp1.timinglee.org/lee/hostname.html -u lee:lee
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master services]# curl -Lk https://myapp1.timinglee.org/lee/aaaa/ -u lee:lee
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master services]# curl -Lk https://myapp1.timinglee.org/lee/aaaa/ -u lee:lee
九.Canary金丝雀发布
1.基于head的灰度发布
[root@master services]# vim 6-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
name: webcluster
spec:
ingressClassName: nginx
rules:
- host: myapp1.timinglee.org
http:
paths:
- backend:
service:
name: myapp1
port:
number: 80
path: /
pathType: Prefix
[root@master services]# kubectl apply -f 6-ingress.yml
ingress.networking.k8s.io/webcluster created
[root@master services]# kubectl describe ingress webcluster
Name: webcluster
Labels: <none>
Namespace: default
Address:
Ingress Class: nginx
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
myapp1.timinglee.org
/ myapp1:80 (10.244.1.60:80)
Annotations: nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 7s nginx-ingress-controller Scheduled for sync
[root@master services]# curl myapp1.timinglee.org
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
#建立新的ingress
[root@master services]# vim 7-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "version"
nginx.ingress.kubernetes.io/canary-by-header-value: "2"
nginx.ingress.kubernetes.io/rewrite-target: /
name: webcluster-new
spec:
ingressClassName: nginx
rules:
- host: myapp1.timinglee.org
http:
paths:
- backend:
service:
name: myapp2
port:
number: 80
path: /
pathType: Prefix
root@master services]# kubectl apply -f 7-ingress.yml
ingress.networking.k8s.io/webcluster-new created
[root@master services]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
webcluster nginx myapp1.timinglee.org 172.25.254.20 80 3m38s
webcluster-new nginx myapp1.timinglee.org 80 6s
[root@master services]# curl myapp1.timinglee.org
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master services]# curl -H "version:2" myapp1.timinglee.org
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
2.基于权重的灰度发布
[root@master services]# vim 7-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
nginx.ingress.kubernetes.io/canary-weight-total: "100"
nginx.ingress.kubernetes.io/rewrite-target: /
name: webcluster-new
spec:
ingressClassName: nginx
rules:
- host: myapp1.timinglee.org
http:
paths:
- backend:
service:
name: myapp2
port:
number: 80
path: /
pathType: Prefix
[root@master services]# kubectl apply -f 7-ingress.yml
ingress.networking.k8s.io/webcluster-new created
[root@master services]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
webcluster nginx myapp1.timinglee.org 172.25.254.20 80 7m37s
webcluster-new nginx myapp1.timinglee.org 172.25.254.20 80 6s
#书写测试脚本
[root@master services]# vim check.sh
#!/bin/bash
v1=0
v2=0
for (( i=0; i<100; i++))
do
response=`curl -s myapp1.timinglee.org |grep -c v1`
v1=`expr $v1 + $response`
v2=`expr $v2 + 1 - $response`
done
echo "v1:$v1, v2:$v2"
[root@master services]# sh check.sh
v1:89, v2:11