Ingress-Nginx与kubernetes 网络

部署 ingress-nginx

官网:

Welcome - Ingress-Nginx Controller

1. 下载镜像

复制代码
docker pull registry.k8s.io/ingress-nginx/controller:v1.13.3

docker pull registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.3

2. 上传到私有仓库

修改镜像标签:

复制代码
docker images | grep ingress-nginx | awk '{print $1":"$2}' \
| awk -F/ '{system("docker tag "$0" reg.westos.org/ingress-nginx/"$3)}'

推送:

复制代码
docker images | grep reg.westos.org/ingress-nginx \
| awk '{system("docker push "$1":"$2)}'


3. 下载部署文件

复制代码
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.13.3/deploy/static/provider/baremetal/deploy.yaml

4. 修改镜像地址

修改 deploy.yaml

将官方镜像:

复制代码
registry.k8s.io/ingress-nginx/controller:v1.13.3

修改为:

复制代码
reg.westos.org/ingress-nginx/controller:v1.13.3

两个 webhook 镜像:

复制代码
registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.3

修改为:

复制代码
reg.westos.org/ingress-nginx/kube-webhook-certgen:v1.6.3

共三处。


5. 部署 ingress-nginx

复制代码
kubectl apply -f deploy.yaml

查看状态:

复制代码
kubectl -n ingress-nginx get pod,svc,deployment

示例:

复制代码
NAME                         READY   STATUS
ingress-nginx-controller     1/1     Running

默认访问方式

裸机环境部署时,默认 Service 类型:

复制代码
kubectl get svc -n ingress-nginx

通常为:

复制代码
TYPE: NodePort

访问方式:

复制代码
http://NodeIP:NodePort

例如:

复制代码
http://192.168.150.101:30080

Ingress 暴露方式

方式一:LoadBalancer + ingress-nginx

适用于:

  • 云平台环境
  • 裸金属环境配合 MetalLB

修改 Service 类型:

复制代码
复制代码
kubectl -n ingress-nginx edit svc ingress-nginx-controller

修改:

复制代码
复制代码
type: LoadBalancer

查看:

复制代码
复制代码
kubectl -n ingress-nginx get svc

示例:

复制代码
复制代码
NAME                       TYPE           EXTERNAL-IP
ingress-nginx-controller   LoadBalancer   192.168.36.101

访问:

复制代码
复制代码
http://192.168.36.101

特点:

优点:

  • 架构简单
  • 支持高可用

缺点:

  • 多一层 Service 转发
  • 性能略有损耗

方式二:DaemonSet + hostNetwork

适用于:

  • 裸金属环境
  • 对性能要求较高场景

特点:

Ingress Controller 直接监听节点网络端口。

请求链路:

复制代码
复制代码
客户端
  ↓
节点IP:80/443
  ↓
Ingress Controller
  ↓
Service
  ↓
Pod

修改部署文件:

updateStrategy


参数解释:

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

查看:

复制代码
kubectl -n ingress-nginx get pod -o wide

如果 Pod IP 与节点 IP 一致,说明使用 hostNetwork。


基于域名的虚拟主机

创建 Ingress

复制代码
复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress

metadata:
  name: ingress-virtual-host

spec:
  ingressClassName: nginx

  rules:
  - host: web.example.com
    http:
      paths:
      - path: /
        pathType: Prefix

        backend:
          service:
            name: web-service
            port:
              number: 80

创建:

复制代码
复制代码
kubectl apply -f ingress-virtual-host.yml

查看:

复制代码
kubectl get ingress

测试前需要配置解析:

复制代码
192.168.150.240 web.example.com

访问:

复制代码
curl web.example.com

多域名访问

复制代码
[root@docker1 harbor]# docker pull yakexi007/myapp:v1
[root@docker1 harbor]# docker tag yakexi007/myapp:v2 reg.westos.org/library/myapp:v2
[root@docker1 harbor]# docker push reg.westos.org/library/myapp:v2

创建两个 Web 服务:

复制代码
web1.example.com  ---> web-v1 Service ---> v1 Pod

web2.example.com  ---> web-v2 Service ---> v2 Pod

创建测试服务

kubectl create -f deploy-web1.yml

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

# cat deploy-web2.yml
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:

复制代码
# cat ingress-virtual-host.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-virtual-host
spec:
  ingressClassName: nginx
  rules:
  - host: web1.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-v1
            port:
              number: 80

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

# kubectl create -f ingress-virtual-host.yml

测试:

复制代码
curl web1.example.com

Hello MyApp | Version: v1


curl web2.example.com

Hello MyApp | Version: v2

基于路径访问

不同 URL 转发到不同 Service。

例如:

复制代码
web.example.com/v1  ---> web-v1

web.example.com/v2  ---> web-v2

kubectl create -f ingress-virtual-path.yml


# cat ingress-virtual-path.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-virtual-path
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: web.example.com
    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

查看ingress资源

复制代码
# kubectl get ingress

# kubectl describe ingress ingress-virtual-path

访问:

复制代码
curl web.example.com/v1

Hello MyApp | Version: v1


curl web.example.com/v2

Hello MyApp | Version: v2

总结

Ingress 提供 Kubernetes 七层流量管理能力:

功能 作用
域名转发 不同域名访问不同服务
路径转发 不同 URL 访问不同服务
TLS HTTPS 加密
认证 Basic Auth 等访问控制
灰度发布 按比例分配流量
负载均衡 自动转发到后端 Pod

Default Backend

复制代码
---
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 默认情况下没有匹配到规则时,会返回默认 404 页面。

可以通过自定义 default backend 修改错误页面。
创建资源

复制代码
# kubectl -n ingress-nginx create -f custom-default-backend.yml
查看
# kubectl -n ingress-nginx get pod,svc

修改 ingress-nginx-controller:

复制代码
复制代码
kubectl -n ingress-nginx edit ds ingress-nginx-controller

添加:

复制代码
复制代码
- --default-backend-service=ingress-nginx/nginx-errors
# 指定默认后端服务(namespace/service)

部署:

复制代码
kubectl -n ingress-nginx create -f custom-default-backend.yml

查看:

复制代码
kubectl -n ingress-nginx get pod,svc

Ingress 未匹配规则时会转发到 nginx-errors。


2. TLS 加密访问

Ingress 可以通过 Secret 保存证书,实现 HTTPS。

创建证书:

复制代码
复制代码
openssl req -x509 -sha256 -nodes \
-days 365 \
-newkey rsa:2048 \
-keyout tls.key \
-out tls.crt \
-subj "/CN=nginxsvc/O=nginxsvc"

创建 Secret:

复制代码
复制代码
kubectl create secret tls tls-secret \
--key tls.key \
--cert tls.crt

Ingress 配置:
创建ingress资源

复制代码
# kubectl delete -f ingress-virtual-host.yml #删除之前的资源不然会冲突

# kubectl create -f ingress-web-tls.yml

# cat ingress-web-tls.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-web-tls
spec:
  tls:
    - hosts:
      - web1.example.com
      - web2.example.com
      secretName: tls-secret
  ingressClassName: nginx
  rules:
  - host: web1.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-v1
            port:
              number: 80

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

强制重定向80到443
# curl -I web1.example.com
HTTP/1.1 308 Permanent Redirect
Date: Fri, 31 Oct 2025 15:56:56 GMT
Content-Type: text/html
Content-Length: 164
Connection: keep-alive
Location: https://web1.example.com

访问:

复制代码
curl -k https://web1.example.com
curl -k https://web2.example.com

3. Basic Auth 认证

使用 htpasswd 创建用户:

复制代码
复制代码
yum install -y httpd-tools

htpasswd -c auth zyl

创建 Secret:

复制代码
kubectl create secret generic basic-auth \
--from-file=auth

创建ingress
# kubectl delete -f ingress-web-tls.yml
# kubectl create -f ingress-web-tls-auth.yml

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 - wxh'
spec:
  tls:
    - hosts:
      - web1.example.com
      - web2.example.com
      secretName: tls-secret
  ingressClassName: nginx
  rules:
  - host: web1.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-v1
            port:
              number: 80

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

kubectl get ingress
kubectl describe ingress ingress-web-tls-auth

测试:

复制代码
curl -u zyl:123456 -k https://web1.example.com

4. Rewrite 重定向

基于路径重写

复制代码
# kubectl create -f ingress-rewrite-1.yml

# cat ingress-rewrite-1.yml
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 - wxh'
    nginx.ingress.kubernetes.io/app-root: /cgi-bin/action
spec:
  tls:
    - hosts:
      - web.example.com
      secretName: tls-secret
  ingressClassName: nginx
  rules:
  - host: web.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

访问:

复制代码
curl -u zyl:123456 -k -I https://web.example.com

请求路径会被重写后转发给后端服务。

基于正则重写

开启正则:

复制代码
annotations:

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

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

示例:

复制代码
path: /testing(/|$)(.*)
pathType: ImplementationSpecific

# kubectl delete -f ingress-rewrite-1.yml
# kubectl create -f ingress-rewrite-2.yml

访问:

复制代码
curl https://web.example.com/testing/cgi-bin/action

会匹配正则并重写路径。


5. Canary 金丝雀发布

金丝雀发布:

先部署新版本,只分配少量流量测试。

优点:

  • 降低新版本故障影响
  • 可以逐步扩大流量

缺点:

  • 发布周期较长

创建旧版本 Ingress

复制代码
apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:
  name: ingress-canary-v1

spec:
  ingressClassName: nginx

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

创建新版本 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"

表示:

10% 流量访问 v2,90%访问 v1。

复制代码
编写测试脚本
# cat ingress-canary.sh
#!/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"

测试:

复制代码
sh ingress-canary.sh

结果:

复制代码
v1:90,v2:10

6. A/B 测试

A/B 测试根据请求信息决定流量方向。

常用方式:

  • Header
  • Cookie

Header 流量切分

Ingress:

复制代码
# cat ingress-ab-header.yml
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:
  - host: myapp.example.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: web-v2
            port:
              number: 80

测试:

复制代码
curl -H "stage:gray" myapp.example.com

匹配 Header 进入 v2。

复制代码
annotations:

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

 nginx.ingress.kubernetes.io/canary-by-cookie: user_from_sz

测试:

复制代码
curl --cookie "user_from_sz=always" myapp.example.com

进入 v2。


7. Multus 多网络插件

作用

Multus CNI 可以让一个 Pod 同时拥有多个网络接口。

默认:

复制代码
Pod
 |
eth0
 |
默认CNI(Calico)

使用 Multus 后:

复制代码
Pod
 |
eth0  主网络
 |
net1  附加网络

主要应用:

  • 多网络隔离
  • NFV
  • 高性能计算
  • 多租户环境

Multus 本身不提供网络,只负责调用其他 CNI 插件。


8. 部署 Multus

下载:

复制代码
wget https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset.yml

拉取镜像:

复制代码
docker pull ghcr.io/k8snetworkplumbingwg/multus-cni:snapshot

上传私有仓库:

复制代码
docker tag \
ghcr.io/k8snetworkplumbingwg/multus-cni:snapshot \
reg.westos.org/multus/multus-cni:snapshot

docker push reg.westos.org/multus/multus-cni:snapshot

修改镜像:

复制代码
image:
 reg.westos.org/multus/multus-cni:snapshot

部署:

复制代码
kubectl apply -f multus-daemonset.yml

查看:

复制代码
kubectl get pods -n kube-system -l app=multus

9. 创建 Macvlan 网络

静态 IP 网络

复制代码
apiVersion: k8s.cni.cncf.io/v1

kind: NetworkAttachmentDefinition

metadata:
  name: macvlan-static

spec:

  config: '{
    "cniVersion":"0.4.0",

    "type":"macvlan",

    "master":"eth0",

    "mode":"bridge",

    "ipam":{
      "type":"static",

      "addresses":[
        {
        "address":"192.168.36.71/24",
        "gateway":"192.168.36.2"
        }
      ]
    }
  }'

参数:

复制代码
type: macvlan        # 使用macvlan插件
master: eth0         # 绑定物理网卡
mode: bridge         # 二层桥接模式

创建多网络接口 Pod

1. 创建静态 Macvlan 网络

先创建 NetworkAttachmentDefinition,用于定义 Pod 的额外网络。

复制代码
# cat macvlan-static.yml
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: macvlan-static
spec:
  config: '{
    "cniVersion": "0.4.0",
    "type": "macvlan",
    "master": "eth0",
    "mode": "bridge",
    "ipam": {
      "type": "static",
      "addresses": [{
        "address": "192.168.36.71/24",
        "gateway": "192.168.36.2"
      }]
    }
  }'

创建:

复制代码
kubectl apply -f macvlan-static.yml

注释:

复制代码
type: macvlan
→ 使用 Macvlan 网络

master: eth0
→ 绑定主机的 eth0 网卡
# 实际环境中需要根据节点真实网卡名称修改

mode: bridge
→ 使用 Macvlan bridge 模式

ipam: static
→ 手动指定额外接口 IP

2. 创建多网络接口 Pod

复制代码
# cat pod-web-multus-static.yml
apiVersion: "v1"
kind: Pod
metadata:
  name: "multus-web"
  labels:
    app: "multus"
  annotations:
    k8s.v1.cni.cncf.io/networks: macvlan-static
spec:
  containers:
  - name: "apache-frontend"
    image: "reg.westos.org/library/httpd:dns"
    ports:
    - containerPort: 80

创建 Pod:

复制代码
kubectl create -f pod-web-multus-static.yml

查看网络:

复制代码
kubectl describe net-attach-def macvlan-static

查看 Pod:

复制代码
kubectl describe pod multus-web

关键配置

复制代码
annotations:
  k8s.v1.cni.cncf.io/networks: macvlan-static

表示:

给这个 Pod 增加 macvlan-static 定义的额外网络接口。

因此 Pod 最终会有两个网络接口,例如:

复制代码
eth0 → 默认 CNI 网络
net1 → Multus + Macvlan 网络

PDF 实验中 Pod 会获得两个 IP,并可以直接通过额外网络 IP 访问业务:

复制代码
curl 192.168.36.71

3. 创建动态 IP 地址池

静态方式需要自己指定 IP,也可以让 Multus 从地址池自动分配。

复制代码
# cat macvlan-pool.yml
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: macvlan-pool    # 从网络名称
spec:
  config: '{
    "cniVersion": "0.4.0",    # 与 macvlan 插件支持的版本匹配
    "type": "macvlan",         # 网络插件类型
    "master": "eth0",          # 绑定主机物理网卡
    "mode": "bridge",           # macvlan bridge 模式
    "ipam": {
      "type": "host-local",     # 自动从本地地址池分配 IP
      "subnet": "192.168.36.0/24",   # Pod 使用的子网
      "rangeStart": "192.168.36.200", # IP 起始范围
      "rangeEnd": "192.168.36.216",   # IP 结束范围
      "gateway": "192.168.36.2"       # 网关
    }
  }'

创建:

复制代码
kubectl apply -f macvlan-pool.yml

和静态方式的区别

复制代码
静态:
ipam = static
自己指定 192.168.36.71

动态:
ipam = host-local
从 192.168.36.200 ~ 192.168.36.216 自动分配

PDF 中给出的动态地址池配置就是这种方式。


4. 创建使用动态地址池的 Pod

复制代码
# cat pod-web-multus-dynamic.yml
apiVersion: "v1"
kind: Pod
metadata:
  name: "multus-web2"
  labels:
    app: "multus"
  annotations:
    k8s.v1.cni.cncf.io/networks: macvlan-pool
spec:
  containers:
  - name: "apache-frontend"
    image: "reg.westos.org/library/httpd:dns"
    ports:
    - containerPort: 80

创建:

复制代码
kubectl create -f pod-web-multus-dynamic.yml

这里最关键的是:

复制代码
annotations:
  k8s.v1.cni.cncf.io/networks: macvlan-pool

表示这个 Pod 使用前面创建的 macvlan-pool 作为额外网络。

这次不需要手动填写 Pod 的额外 IP,由:

复制代码
host-local

从:

复制代码
192.168.36.200 ~ 192.168.36.216

范围中进行分配。

网络策略 NetworkPolicy

1. NetworkPolicy 简介

NetworkPolicy 用于控制 Pod 的网络流量,主要分为:

复制代码
Ingress → 控制进入 Pod 的流量
Egress  → 控制 Pod 发出的流量

NetworkPolicy 必须依赖支持它的网络插件才能真正生效,单独创建 NetworkPolicy 资源但没有对应控制器,是没有实际作用的。

默认情况下:

复制代码
Pod 入站:允许
Pod 出站:允许

2. 限制 Pod 流量

创建策略:

复制代码
kubectl apply -f networkpolicy-test1.yml

查看:

复制代码
kubectl describe networkpolicies networkpolicy-test1

配置:

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy

metadata:
  name: networkpolicy-test1
  namespace: default

spec:
  podSelector:
    matchLabels:
      app: web

  policyTypes:
  - Ingress

  ingress:
  - from:
    - podSelector:
        matchLabels:
          run: test
    ports:
    - protocol: TCP
      port: 80

配置含义

复制代码
podSelector:
  app=web

表示被保护的目标 Pod

复制代码
from:
  podSelector:
    run=test

表示允许访问目标 Pod 的来源 Pod

复制代码
port: 80

表示只允许访问目标 Pod 的 TCP 80 端口。

所以整体可以理解成:

复制代码
run=test 的 Pod
       ↓
   TCP 80
       ↓
app=web 的 Pod

3. 创建测试 Pod

使用:

复制代码
kubectl run demo --image reg.westos.org/library/busyboxplus -it --rm

测试:

复制代码
curl 10.244.141.240

修改测试 Pod 的标签:

复制代码
kubectl get pod demo --show-labels

原来:

复制代码
run=demo

修改为策略要求的:

复制代码
kubectl label pod demo run=test --overwrite

再次查看:

复制代码
kubectl get pod demo --show-labels

变成:

复制代码
run=test

这样 demo 才满足 NetworkPolicy 的来源条件。

遇到的问题

测试 NetworkPolicy 时必须有:

复制代码
测试 Pod
   ↓
目标 Pod

如果 test Namespace 里只有 demo 一个 Pod,那么不能很好地测试 Pod → Pod 的访问控制。

另外,实际使用 busybox 时遇到过:

复制代码
curl: not found

因为普通 BusyBox 不一定带 curl,可以使用:

复制代码
wget -O- http://目标PodIP

进行测试。


4. 限制 Namespace 流量

创建:

复制代码
kubectl apply -f networkpolicy-test2.yml

查看:

复制代码
kubectl describe networkpolicies networkpolicy-test2

配置核心:

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy

metadata:
  name: networkpolicy-test2
  namespace: default

spec:
  podSelector:
    matchLabels:
      app: web1

  policyTypes:
  - Ingress

  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          project: test
      podSelector:
        matchLabels:
          run: test

    ports:
    - protocol: TCP
      port: 80

这里增加了:

复制代码
namespaceSelector:
  matchLabels:
    project: test

表示来源 Pod 所在的 Namespace 必须满足:

复制代码
project=test

同时来源 Pod 还必须满足:

复制代码
run=test

所以:

复制代码
Namespace:
project=test

      +

Pod:
run=test

      ↓

允许访问 app=web1 的 Pod

5. 创建 test Namespace

复制代码
kubectl create ns test

查看

复制代码
kubectl get ns --show-labels test

给 Namespace 添加标签:

复制代码
kubectl label ns test project=test

查看:

复制代码
kubectl get ns --show-labels test

最终:

复制代码
test   ...   project=test

这个标签就是 namespaceSelector 使用的匹配条件。


6. Harbor 私有仓库认证

因为测试 Pod 使用:

复制代码
reg.westos.org/...

私有 Harbor 镜像,所以需要镜像仓库认证。

创建 Secret:

复制代码
kubectl create -f secret-registry.yml -n test

查看:

复制代码
kubectl get secret -n test

Secret:

复制代码
myregkey

类型:

复制代码
kubernetes.io/dockerconfigjson

作用:

复制代码
Pod
 ↓
拉取 Harbor 私有镜像
 ↓
myregkey 提供认证信息

遇到的报错

执行:

复制代码
kubectl run demo --image reg.westos.org/library/busybox -n test

出现:

复制代码
authorization failed: no basic auth credentials

就是镜像仓库认证没有正确配置。

而且 Secret 是 Namespace 隔离的

复制代码
default/myregkey

不能直接给:

复制代码
test/demo

使用。


7. ServiceAccount 绑定镜像仓库 Secret

创建:

复制代码
kubectl apply -f sa-registry.yml -n test

sa-registry.yml

复制代码
apiVersion: v1
kind: ServiceAccount

metadata:
  name: default

imagePullSecrets:
- name: myregkey

作用:

复制代码
test Namespace
      ↓
default ServiceAccount
      ↓
imagePullSecrets: myregkey
      ↓
Pod 拉取 Harbor 镜像

这样以后使用这个 ServiceAccount 创建 Pod 时,可以自动使用 myregkey


8. 同时限制 Namespace 和 Pod

创建:

复制代码
kubectl apply -f networkpolicy-test3.yml

查看

复制代码
kubectl describe networkpolicies networkpolicy-test3

核心配置:

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy

metadata:
  name: networkpolicy-test3
  namespace: default

spec:
  podSelector:
    matchLabels:
      app: web2

  policyTypes:
  - Ingress

  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          project: test
      podSelector:
        matchLabels:
          run: test

    ports:
    - protocol: TCP
      port: 80

这里的条件更加严格:

复制代码
来源 Namespace
project=test
        +
来源 Pod
run=test
        ↓
访问目标
app=web2
        ↓
TCP 80

所以 强调:

Namespace 和 Pod 都要满足对应标签条件才能访问。


9. 测试 networkpolicy-test3

test Namespace 中的 demo 添加标签:

复制代码
kubectl -n test label pod demo run=test --overwrite

创建测试 Pod:

复制代码
kubectl run demo \
  --image reg.westos.org/library/busyboxplus \
  -it --rm -n test

测试目标 web2

复制代码
curl 10.244.141.236

PDF 中测试可以正常访问 web2


10. 限制集群外部流量

创建:

复制代码
kubectl apply -f networkpolicy-test4.yml

核心配置:

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy

metadata:
  name: networkpolicy-test4
  namespace: default

spec:
  podSelector:
    matchLabels:
      app: web

  policyTypes:
  - Ingress

  ingress:
  - from:
    - ipBlock:
        cidr: 192.168.0.0/16
        except:
        - 192.168.36.0/24

    ports:
    - protocol: TCP
      port: 80

IPBlock 含义

复制代码
cidr: 192.168.0.0/16

允许这个网段。

复制代码
except:
- 192.168.36.0/24

但是排除 192.168.36.0/24

也就是:

复制代码
192.168.0.0/16
      ↓
排除 192.168.36.0/24

11. 测试外部访问

策略创建之前:

复制代码
kubectl run demo \
  --image reg.westos.org/library/busyboxplus \
  -it --rm -n test

访问目标 Pod:

复制代码
curl 10.244.141.240

可以正常访问。

创建策略:

复制代码
kubectl apply -f networkpolicy-test4.yml

之后, 验证:

复制代码
集群内部访问正常
集群外部访问受到限制

查看:

复制代码
kubectl describe networkpolicies networkpolicy-test4

主要看:

复制代码
IPBlock
CIDR: 192.168.0.0/16
Except: 192.168.36.0/24

12. LoadBalancer + NetworkPolicy 测试

查看 LoadBalancer:

复制代码
kubectl get svc web-service-lb

环境:

复制代码
web-service-lb   LoadBalancer   ...   192.168.36.100   80

测试:

复制代码
curl 192.168.36.100

这里:

复制代码
192.168.36.100

LoadBalancerEXTERNAL-IP


13. 回收 NetworkPolicy

实验完成后:

复制代码
kubectl delete networkpolicies --all
相关推荐
wdfk_prog6 小时前
ROS教程08:从 TransportTCP::connect() 追到 TCPROS Connection Header、序列化与 Socket 数据传输
运维·缓存·docker·容器·ros
做运维的阿瑞6 小时前
Python 标准库汇总:分类速览与常用模块清单
linux·运维·python
百万蹄蹄向前冲7 小时前
密码都对Node.js却连不上Linux数据库
linux·mysql
广州宏帝箱包7 小时前
出口箱包的包装标准:防潮、防摔、运输安全的设计要点
大数据·网络
彧azz7 小时前
Linux 网络编程学习总结
linux·网络·笔记·学习·面试
日常筹谋记7 小时前
自动化仓储安全防护工况评估:明治传感器AS-33C技术适配性分析
大数据·运维·创业创新·业界资讯
updayday8547 小时前
离职域账号状态变更与Ping64操作记录核对
大数据·网络·数据库·安全·智能路由器
susplus8 小时前
【ARM 裸机开发 (IMX6ULL-mini)】GNU工具、Makefile 工程构建、链接脚本详解|C 语言点灯 + 蜂鸣器驱动
linux·arm·makefile·imx6ull
Shadow(⊙o⊙)8 小时前
Linux进阶知识1.0
linux·运维·服务器
>Andre<8 小时前
UFS5.0标准中文全译·卷一:范围、术语与架构
android·linux·嵌入式硬件