04 (下) | K8S微服务实战:从 Service 到金丝雀发布

实验集合:

一.创建一个clusterIP微服务

bash 复制代码
[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工作模式

bash 复制代码
[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的轮询列表中的信息即可

三.微服务解析

bash 复制代码
[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

bash 复制代码
[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的建立

bash 复制代码
[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

bash 复制代码
[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>

2.部署metallb

bash 复制代码
[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

bash 复制代码
[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.安装

bash 复制代码
[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和控制器

bash 复制代码
[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代理

bash 复制代码
[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加密

bash 复制代码
[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认证

bash 复制代码
[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

bash 复制代码
[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

bash 复制代码
[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的灰度发布

bash 复制代码
[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.基于权重的灰度发布

bash 复制代码
[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
​
相关推荐
艾莉丝努力练剑2 小时前
【Linux网络】网络层IP协议(二):网段划分
linux·运维·服务器·网络·tcp/ip·udp
江华森2 小时前
Jenkins 运维管理实战博客大纲
运维·jenkins
艾莉丝努力练剑2 小时前
【Linux网络】网络层IP协议(三):网段划分(下)
linux·运维·服务器·网络·tcp/ip
尔染君子2 小时前
嵌入式Linux驱动开发(基于树莓派rasberrypi 5的LED驱动开发)
linux·运维·驱动开发
上海云盾安全满满2 小时前
服务器CPU跑满的原因及解决办法
运维·服务器
Plastic garden2 小时前
K8s知识(5) Kubernetes 存储 PV
kubernetes
tobias.b2 小时前
供电不稳定、无UPS/无双电源环境下服务器高可用完整方案
运维·服务器
团象科技2 小时前
从出海业务落地视角观察 海外服务器跑开源软件的实操逻辑演变
运维·服务器·开源软件
加成BUFF2 小时前
第七天 ROS《 参数服务器与Launch文件》
运维·ros·参数服务器