首页 > 其他分享 >第9周-elk-k8s网络

第9周-elk-k8s网络

时间:2023-05-10 19:25:24浏览次数:45  
标签:elk ingress 网络 nginx io pod k8s Pod

一、日志收集案例-容器内置日志收集

收集架构

img

应用程序以tomcat为例

1构建镜像

Dockerfile

FROM harbor.jackedu.net/baseimage/tomcat-base:v8.5.43 

ADD catalina.sh /apps/tomcat/bin/catalina.sh
ADD server.xml /apps/tomcat/conf/server.xml
#ADD myapp/* /data/tomcat/webapps/myapp/
ADD myapp.tar.gz /data/tomcat/webapps/myapp/
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
#ADD filebeat.yml /etc/filebeat/filebeat.yml 
RUN chown  -R tomcat.tomcat /data/ /apps/
ADD filebeat-7.12.1-x86_64.rpm /tmp/
RUN cd /tmp && yum localinstall -y filebeat-7.12.1-x86_64.rpm
ADD filebeat.yml /etc/filebeat/filebeat.yml 

EXPOSE 8080 8443

CMD ["/apps/tomcat/bin/run_tomcat.sh"]

filebeat.yml

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /apps/tomcat/logs/catalina.out
  fields:
    type: filebeat-tomcat-catalina
- type: log
  enabled: true
  paths:
    - /apps/tomcat/logs/localhost_access_log.*.txt 
  fields:
    type: filebeat-tomcat-accesslog
filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: false
setup.template.settings:
  index.number_of_shards: 1
setup.kibana:

output.kafka:
  hosts: ["192.168.44.23:9092"]
  required_acks: 1
  topic: "filebeat-magedu-app1"
  compression: gzip
  max_message_bytes: 1000000

run_tomcat.sh容器运行脚本

#!/bin/bash
#echo "nameserver 223.6.6.6" > /etc/resolv.conf
#echo "192.168.7.248 k8s-vip.example.com" >> /etc/hosts

/usr/share/filebeat/bin/filebeat -e -c /etc/filebeat/filebeat.yml -path.home /usr/share/filebeat -path.config /etc/filebeat -path.data /var/lib/filebeat -path.logs /var/log/filebeat &
su - tomcat -c "/apps/tomcat/bin/catalina.sh start"
tail -f /etc/hosts

构建脚本

nerdctl build -t  harbor.jackedu.net/app/tomcat-app1:v2  .
nerdctl push harbor.jackedu.net/app/tomcat-app1:v2

2.运行web服务

2.1RBAC鉴权

授予web命名空间内default服务帐户具有对集群内namespace、pod、node等资源进行get、watch、list的权限

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: filebeat-serviceaccount-clusterrole
  labels:
    k8s-app: filebeat-serviceaccount-clusterrole
rules:
- apiGroups: [""] # "" indicates the core API group
  resources:
  - namespaces
  - pods
  - nodes
  verbs:
  - get
  - watch
  - list

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: filebeat-serviceaccount-clusterrolebinding
subjects:
- kind: ServiceAccount
  name: default
  namespace: magedu
roleRef:
  kind: ClusterRole
  name: filebeat-serviceaccount-clusterrole
  apiGroup: rbac.authorization.k8s.io
kubectl get clusterrole filebeat-serviceaccount-clusterrole 
NAME                                  CREATED AT
filebeat-serviceaccount-clusterrole   2023-04-11T09:23:44Z

kubectl get clusterrolebinding filebeat-serviceaccount-clusterrolebinding
NAME                                         ROLE                                              AGE
filebeat-serviceaccount-clusterrolebinding   ClusterRole/filebeat-serviceaccount-clusterrole   3m4s
2.2部署服务
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: web-tomcat-app1-filebeat-deployment-label
  name: web-tomcat-app1-filebeat-deployment
  namespace: test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web-tomcat-app1-filebeat-selector
  template:
    metadata:
      labels:
        app: web-tomcat-app1-filebeat-selector
    spec:
      containers:
      - name: web-tomcat-app1-filebeat-container
        image: harbor.jackedu.net/web/tomcat-app1:v2
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
        resources:
          limits:
            cpu: 1
            memory: "512Mi"
          requests:
            cpu: 500m
            memory: "512Mi"

查看

kubectl get po -n test
NAME                                                   READY   STATUS      RESTARTS       AGE
python-nginx-deployment-5c658bf86b-nv7sm               1/1     Running     4 (6h4m ago)   9d
ubuntu1804                                             0/1     Completed   0              40d
web-tomcat-app1-filebeat-deployment-64c569957f-jvddj   1/1     Running     0              4s

创建service

---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: web-tomcat-app1-filebeat-service-label
  name: web-tomcat-app1-filebeat-service
  namespace: test
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
    nodePort: 30092
  selector:
    app: web-tomcat-app1-filebeat-selector
2.3配置logstash服务器

/etc/logstash/conf.d/logstash.conf

input {
  kafka {
    bootstrap_servers => "192.168.44.23:9092"
    topics => ["filebeat-magedu-app1"]
    codec => "json"
  }
}




output {
  if [fields][type] == "filebeat-tomcat-catalina" {
    elasticsearch {
      hosts => ["192.168.44.21:9200","192.168.44.22:9200"]
      index => "filebeat-tomcat-catalina-%{+YYYY.MM.dd}"
    }}

  if [fields][type] == "filebeat-tomcat-accesslog" {
    elasticsearch {
      hosts => ["192.168.44.21:9200","192.168.44.22:9200"]
      index => "filebeat-tomcat-accesslog-%{+YYYY.MM.dd}"
    }}

}

重启服务

systemctl restart logstash

2.4验证elasticsearch数据

2.5kibana展示日志数据

日志展示

access日志

catalina日志

二、overlay与underlay通信总结

Overlay网络是通过网络虚拟化技术,在同一张Underlay网络上构建出的一张或者多张虚拟的逻辑网络。不同的Overlay网络虽然共享Underlay网络中的设备和线路,但是Overlay网络中的业务与Underlay网络中的物理组网和互联技术相互解耦。Overlay网络的多实例化,既可以服务于同一租户的不同业务(如多个部门),也可以服务于不同租户,是SD-WAN以及数据中心等解决方案使用的核心组网技术。

Overlay网络和Underlay网络是一组相对概念,Overlay网络是建立在Underlay网络上的逻辑网络。而为什么需要建立Overlay网络,就要从底层的Underlay网络的概念以及局限讲起。

2.1Underlay网络

Underlay网络正如其名,是Overlay网络的底层物理基础。

如下图所示,Underlay网络可以是由多个类型设备互联而成的物理网络,负责网络之间的数据包传输。

img

典型的Underlay网络

在Underlay网络中,互联的设备可以是各类型交换机、路由器、负载均衡设备、防火墙等,但网络的各个设备之间必须通过路由协议来确保之间IP的连通性。

Underlay网络可以是二层也可以是三层网络。其中二层网络通常应用于以太网,通过VLAN进行划分。三层网络的典型应用就是互联网,其在同一个自治域使用OSPF、IS-IS等协议进行路由控制,在各个自治域之间则采用BGP等协议进行路由传递与互联。随着技术的进步,也出现了使用MPLS这种介于二三层的WAN技术搭建的Underlay网络。

然而传统的网络设备对数据包的转发都基于硬件,其构建而成的Underlay网络也产生了如下的问题:

  • 由于硬件根据目的IP地址进行数据包的转发,所以传输的路径依赖十分严重。
  • 新增或变更业务需要对现有底层网络连接进行修改,重新配置耗时严重。
  • 互联网不能保证私密通信的安全要求。
  • 网络切片和网络分段实现复杂,无法做到网络资源的按需分配。
  • 多路径转发繁琐,无法融合多个底层网络来实现负载均衡。

2.2 Overlay网络

为了摆脱Underlay网络的种种限制,现在多采用网络虚拟化技术在Underlay网络之上创建虚拟的Overlay网络。

img

Overlay网络拓扑

在Overlay网络中,设备之间可以通过逻辑链路,按照需求完成互联形成Overlay拓扑。

相互连接的Overlay设备之间建立隧道,数据包准备传输出去时,设备为数据包添加新的IP头部和隧道头部,并且被屏蔽掉内层的IP头部,数据包根据新的IP头部进行转发。当数据包传递到另一个设备后,外部的IP报头和隧道头将被丢弃,得到原始的数据包,在这个过程中Overlay网络并不感知Underlay网络。

Overlay网络有着各种网络协议和标准,包括VXLAN、NVGRE、SST、GRE、NVO3、EVPN等。

随着SDN技术的引入,加入了控制器的Overlay网络,有着如下的优点:

  • 流量传输不依赖特定线路。Overlay网络使用隧道技术,可以灵活选择不同的底层链路,使用多种方式保证流量的稳定传输。
  • Overlay网络可以按照需求建立不同的虚拟拓扑组网,无需对底层网络作出修改。
  • 通过加密手段可以解决保护私密流量在互联网上的通信。
  • 支持网络切片与网络分段。将不同的业务分割开来,可以实现网络资源的最优分配。
  • 支持多路径转发。在Overlay网络中,流量从源传输到目的可通过多条路径,从而实现负载分担,最大化利用线路的带宽。

名称解释

VxLAN

VxLAN全称是VirtualeXtensibleLocal Area Network (虚拟扩展本地局域网)主要有Cisco推出,vxlan是一个VLAN 的扩展协议,是由lETF定义的NVO3 NetworkVirtualization overLaver3) 标准技术之一,VXLAN的特点是将L2的以太帧封装到UDP报文 (即L2overL4) 中,并在L3网络中传输,即使用MACin UDP的方法对报文进行重新封装,VXLAN 本质上是一种verlav的隧道封装技术,它将L2的以太网帧封装成L4的UDP数据报,然后在L3的网络中传输,效果就像L2的以太网帧在一个广播域中传输一样,实际上L2的以太网帧跨越了L3网络传输但是缺不受L3网络的限制,vxlan采用24位标识vlan ID号,因此可以支持224=16777216个vlan,其可扩展性比vlan强大的多,可以支持大规模数据中心的网络需求。

(/i/l/?n=23&i=blog/1394626/202305/1394626-20230510185729447-1561425246.png)

IVTEP(VXLANTunnelEndpoint vxlan隧道端点VTEP是VXLAN网络的边缘设备,是VXLAN隧道的起点和终点,VXLAN对用户原始数据帧的封装和解封装均在VTEP上进行,用于VXLAN报文的封装和解封装,VTEP与物理网络相连,分配的地址为物理网IP地址,VXLAN报文中源IP地址为本节点的VTEP地址,VXLAN报文中目的IP地址为对端节点的VTEP地址,一对VTEP地址就对应着一个VXLAN隧道,服务器上的虚拟交换机(隧道flannel.1就是VTEP),比如一个虚拟机网络中的多个vxlan就需要多个VTEP对不同网络的报文进行封装与解封装。

VNI (VXLAN Network ldentifier) : VXLAN网络标识VNI类似VLANID,用于区分VXLAN段,不同VXLAN段的虚拟机不能直接二层相互通信,一个VNI表示一个租户,即使多人终端用户属于同一个VN也表示一个租户。

NVGRE: Network Virtualization using Generic Routing Encapsulation,主要支持者是Microsoft,与VXLAN不同的是,NVGRE没有采用标准传输协议 (TCP/UDP) ,而是借助通用路由封装协议(GRE) ,NVGRE使用GRE头部的低24位作为租户网络标识符 (TNI) ,与VXLAN一样可以支持1777216个vlan.

三、网络组件flannel总结

3.1 CNI

在理解 CNI 机制以及 Flannel 等具体实现方案之前,首先要理解问题的背景,这里从 kubernetes 网络模型开始回顾。

从底层网络来看,kubernetes 的网络通信可以分为三层去看待:

  • Pod 内部容器通信;
  • 同主机 Pod 间容器通信;
  • 跨主机 Pod 间容器通信;

对于前两点,其网络通信原理其实不难理解。

  1. 对于 Pod 内部容器通信,由于 Pod 内部的容器处于同一个 Network Namespace 下(通过 Pause 容器实现),即共享同一网卡,因此可以直接通信。
  2. 对于同主机 Pod 间容器通信,Docker 会在每个主机上创建一个 Docker0 网桥,主机上面所有 Pod 内的容器全部接到网桥上,因此可以互通。

而对于第三点,跨主机 Pod 间容器通信,Docker 并没有给出很好的解决方案,而对于 Kubernetes 而言,跨主机 Pod 间容器通信是非常重要的一项工作,但是有意思的是,Kubernetes 并没有自己去解决这个问题,而是专注于容器编排问题,对于跨主机的容器通信则是交给了第三方实现,这就是 CNI 机制。

CNI,它的全称是 Container Network Interface,即容器网络的 API 接口。kubernetes 网络的发展方向是希望通过插件的方式来集成不同的网络方案, CNI 就是这一努力的结果。CNI 只专注解决容器网络连接和容器销毁时的资源释放,提供一套框架,所以 CNI 可以支持大量不同的网络模式,并且容易实现。平时比较常用的 CNI 实现有 Flannel、Calico、Weave 等。

CNI 插件通常有三种实现模式:

  • Overlay:靠隧道打通,不依赖底层网络;
  • 路由:靠路由打通,部分依赖底层网络;
  • Underlay:靠底层网络打通,强依赖底层网络;

在选择 CNI 插件时是要根据自己实际的需求进行考量,比如考虑 NetworkPolicy 是否要支持 Pod 网络间的访问策略,可以考虑 Calico、Weave;Pod 的创建速度,Overlay 或路由模式的 CNI 插件在创建 Pod 时比较快,Underlay 较慢;网络性能,Overlay 性能相对较差,Underlay 及路由模式相对较快。

3.2 Flannel的工作原理

Flannel 实质上就是一种 Overlay 网络,也就是将 TCP 数据包装在另一种网络包里面进行路由转发和通信,目前已经支持 UDP、VxLAN、AWS VPC 和 GCE 路由等数据转发方式。

Flannel会在每一个宿主机上运行名为 flanneld 代理,其负责为宿主机预先分配一个子网,并为 Pod 分配IP地址。Flannel 使用Kubernetes 或 etcd 来存储网络配置、分配的子网和主机公共IP等信息。数据包则通过 VXLAN、UDP 或 host-gw 这些类型的后端机制进行转发。

Flannel 规定宿主机下各个Pod属于同一个子网,不同宿主机下的Pod属于不同的子网。

3.3 Flannel 工作模式

支持3种实现:UDP、VxLAN、host-gw

  • UDP 模式:使用设备 flannel.0 进行封包解包,不是内核原生支持,频繁地内核态用户态切换,性能非常差;
  • VxLAN 模式:使用 flannel.1 进行封包解包,内核原生支持,性能较强;
  • host-gw 模式:无需 flannel.1 这样的中间设备,直接宿主机当作子网的下一跳地址,性能最强;

host-gw的性能损失大约在10%左右,而其他所有基于VxLAN“隧道”机制的网络方案,性能损失在20%~30%左右。

3.3.1 UDP 模式

官方已经不推荐使用 UDP 模式,性能相对较差。

UDP 模式的核心就是通过 TUN 设备 flannel0 实现。TUN设备是工作在三层的虚拟网络设备,功能是:在操作系统内核和用户应用程序之间传递IP包。 相比两台宿主机直接通信,多出了 flanneld 的处理过程,这个过程,使用了 flannel0 这个TUN设备,仅在发出 IP包的过程中经过多次用户态到内核态的数据拷贝(linux的上下文切换代价比较大),所以性能非常差,原理如下:

img

以flannel0为例,操作系统将一个IP包发给flannel0,flannel0把IP包发给创建这个设备的应用程序:flannel进程(内核态->用户态) 相反,flannel进程向flannel0发送一个IP包,IP包会出现在宿主机的网络栈中,然后根据宿主机的路由表进行下一步处理(用户态->内核态) 当IP包从容器经过docker0出现在宿主机,又根据路由表进入flannel0设备后,宿主机上的flanneld进程就会收到这个IP包

flannel管理的容器网络里,一台宿主机上的所有容器,都属于该宿主机被分配的“子网”,子网与宿主机的对应关系,存在Etcd中(例如Node1的子网是100.96.1.0/24,container-1的IP地址是100.96.1.2)

当flanneld进程处理flannel0传入的IP包时,就可以根据目的IP地址(如100.96.2.3),匹配到对应的子网(比如100.96.2.0/24),从Etcd中找到这个子网对应的宿主机的IP地址(10.168.0.3)

然后 flanneld 在收到container-1给container-2的包后,把这个包直接封装在UDP包里,发送给Node2(UDP包的源地址,就是Node1,目的地址是Node2)

每台宿主机的flanneld都监听着8285端口,所以flanneld只要把UDP发给Node2的8285端口就行了。然后Node2的flanneld再把IP包发送给它所管理的TUN设备flannel0,flannel0设备再发给docker0

3.3.2VxLAN模式

VxLAN,即Virtual Extensible LAN(虚拟可扩展局域网),是Linux本身支持的一网种网络虚拟化技术。VxLAN可以完全在内核态实现封装和解封装工作,从而通过“隧道”机制,构建出 Overlay 网络(Overlay Network)

VxLAN的设计思想是: 在现有的三层网络之上,“覆盖”一层虚拟的、由内核VxLAN模块负责维护的二层网络,使得连接在这个VxLAN二层网络上的“主机”(虚拟机或容器都可以),可以像在同一个局域网(LAN)里那样自由通信。 为了能够在二层网络上打通“隧道”,VxLAN会在宿主机上设置一个特殊的网络设备作为“隧道”的两端,叫VTEP:VxLAN Tunnel End Point(虚拟隧道端点) 原理如下:

img

  1. flannel.1设备,就是VxLAN的VTEP(既有IP地址,也有MAC地址),与UDP模式类似,当container-1发出请求后,请求container-2地址10.1.16.3的IP包,会先出现在docker网桥,再路由到本机的flannel.1设备进行处理(进站),为了能够将“原始IP包”封装并发送到正常的主机,VxLAN需要找到隧道的出口:宿主机的VTEP设备,这个设备信息,由宿主机的flanneld进程维护
  2. VTEP设备之间通过二层数据帧进行通信 源VTEP设备收到原始IP包后,在上面加上一个目的MAC地址,封装成一个内部数据帧,发送给目的VTEP设备(获取 MAC地址需要通过三层IP地址查询,这是ARP表的功能)

​ 3.封装过程只是加了一个二层头,不会改变“原始IP包”的内容 这些VTEP设备的MAC地址,对宿主机网络来说没什么实际意义,称为内部数据帧,并不能在宿主机的二层网络传输,Linux内核还需要把它进一步封装成为宿主机的一个普通的数据帧,好让它带着“内部数据帧”通过宿主机的eth0进行传输

​ 4.Linux会在内部数据帧前面,加上一个VxLAN头,VxLAN头里有一个重要的标志叫VNI,它是VTEP识别某个数据帧是不是应该归自己处理的重要标识。 在Flannel中,VNI的默认值是1,这也是为什么宿主机的VTEP设备都叫flannel.1的原因

​ 5.一个flannel.1设备只知道另一端flannel.1设备的MAC地址,却不知道对应的宿主机地址是什么。 在linux内核里面,网络设备进行转发的依据,来自FDB的转发数据库,这个flannel.1网桥对应的FDB信息,是由flanneld进程维护的

​ 6.linux内核再在IP包前面加上二层数据桢头,把Node2的MAC地址填进去。这个MAC地址本身,是Node1的ARP表要学习的,需 Flannel维护,这时候Linux封装的“外部数据桢”的格式如下

img

​ 7.然后Node1的flannel.1设备就可以把这个数据桢从eth0发出去,再经过宿主机网络来到Node2的eth0 Node2的内核网络栈会发现这个数据桢有VxLAN Header,并且VNI为1,Linux内核会对它进行拆包,拿到内部数据桢,根据VNI的值,所它交给Node2的flannel.1设备

3.3.3 host-gw模式

Flannel 第三种协议叫 host-gw (host gateway),这是一种纯三层网络的方案,性能最高,即 Node 节点把自己的网络接口当做 pod 的网关使用,从而使不同节点上的 node 进行通信,这个性能比 VxLAN 高,因为它没有额外开销。不过他有个缺点, 就是各 node 节点必须在同一个网段中

img

howt-gw 模式的工作原理,就是将每个Flannel子网的下一跳,设置成了该子网对应的宿主机的 IP 地址,也就是说,宿主机(host)充当了这条容器通信路径的“网关”(Gateway),这正是 host-gw 的含义。

所有的子网和主机的信息,都保存在 Etcd 中,flanneld 只需要 watch 这些数据的变化 ,实时更新路由表就行了。 核心是IP包在封装成帧的时候,使用路由表的“下一跳”设置上的MAC地址,这样可以经过二层网络到达目的宿主机。

另外,如果两个 pod 所在节点在同一个网段中 ,可以让 VxLAN 也支持 host-gw 的功能, 即直接通过物理网卡的网关路由转发,而不用隧道 flannel 叠加,从而提高了 VxLAN 的性能,这种 flannel 的功能叫 directrouting。

3.4 Flannel 通信过程描述
3.4.1 UDP 模式

UDP模式跨主机容器间通信过程如下图所示:

img

上图是 Flannel 在 UDP 模式下一个数据包经过封包、传输以及拆包的示意图,从这个图中可以看出两台机器的 docker0 分别处于不同的段:10.1.20.1/24 和 10.1.15.1/24 ,如果从 Web App Frontend1 pod(10.1.15.2)去连接另一台主机上的 Backend Service2 pod(10.1.20.3),网络包从宿主机 192.168.0.100 发往 192.168.0.200,内层容器的数据包被封装到宿主机的 UDP 里面,并且在外层包装了宿主机的 IP 和 mac 地址。这就是一个经典的 overlay 网络,因为容器的 IP 是一个内部 IP,无法从跨宿主机通信,所以容器的网络互通,需要承载到宿主机的网络之上

3.4.2 VxLAN 模式

VxLAN 模式在源容器宿主机中的数据传递过程如下:

1)源容器向目标容器发送数据,数据首先发送给 docker0 网桥

在源容器内容查看路由信息:

$ kubectl exec -it -p {Podid} -c {ContainerId} -- ip route

2)docker0 网桥接受到数据后,将其转交给flannel.1虚拟网卡处理

docker0 收到数据包后,docker0 的内核栈处理程序会读取这个数据包的目标地址,根据目标地址将数据包发送给下一个路由节点: 查看源容器所在Node的路由信息:

$ ip route

3)flannel.1 接受到数据后,对数据进行封装,并发给宿主机的eth0

flannel.1收到数据后,flannelid会将数据包封装成二层以太包。 Ethernet Header的信息:

  • From: 源容器flannel.1虚拟网卡的MAC地址
  • To: 目录容器flannel.1虚拟网卡的MAC地址

4)对在flannel路由节点封装后的数据,进行再封装后,转发给目标容器Node的eth0;

由于目前的数据包只是vxlan tunnel上的数据包,因此还不能在物理网络上进行传输。因此,需要将上述数据包再次进行封装,才能源容器节点传输到目标容器节点,这项工作在由linux内核来完成。 Ethernet Header的信息:

  • From: 源容器Node节点网卡的MAC地址
  • To: 目录容器Node节点网卡的MAC地址

IP Header的信息:

  • From: 源容器Node节点网卡的IP地址
  • To: 目录容器Node节点网卡的IP地址

通过此次封装,就可以通过物理网络发送数据包。

在目标容器宿主机中的数据传递过程:

5)目标容器宿主机的eth0接收到数据后,对数据包进行拆封,并转发给flannel.1虚拟网卡;

6)flannel.1 虚拟网卡接受到数据,将数据发送给docker0网桥;

7)最后,数据到达目标容器,完成容器之间的数据通信。

四、网络组件caclico总结

五、NetworkPolicy Ingress及Egress简介及案例

5.1Network介绍

NetworkPolicy(网络策略)说明一组 Pod 之间是如何被允许互相通信,以及如何与其它网络 Endpoint 进行通信。 NetworkPolicy 资源使用标签来选择 Pod,并定义了一些规则,这些规则指明允许什么流量进入到选中的 Pod 上。

Network Policy 的作用对象是 Pod,也可以应用到 Namespace 和集群的 Ingress、Egress 流量。Network Policy 是作用在 L3/4 层的,即限制的是对 IP 地址和端口的访问,如果需要对应用层做访问限制需要使用如 Istio 这类 Service Mesh。

Pod之间能否通信可通过如下三种组合进行确认:

1.其他被允许的Pods(例如:Pod无法限制对自身的访问)

2.被允许访问的namespace

3.IP CIDR(例如:与Pod运行所在节点的通信总是被允许)

img

Pod 隔离的两种类型:

Pod 有两种隔离: 出口隔离和入口隔离。

默认情况下,一个 Pod 的出口是非隔离的,即所有外向连接都是被允许的。如果有任何的 NetworkPolicy 选择该 Pod 并在其 policyTypes 中包含 “Egress”,则该 Pod 是出口隔离的。当一个 Pod 的出口被隔离时, 唯一允许的来自 Pod 的连接是适用于出口的 Pod 的某个 NetworkPolicy 的 egress 列表所允许的连接。 这些 egress 列表的效果是相加的。

默认情况下,一个 Pod 对入口是非隔离的,即所有入站连接都是被允许的。如果有任何的 NetworkPolicy 选择该 Pod 并在其 policyTypes 中包含 “Ingress”,则该 Pod 被隔离入口。当一个 Pod 的入口被隔离时,唯一允许进入该 Pod 的连接是适用于入口的 Pod 的某个 NetworkPolicy 的 ingress 列表所允许的连接。这些 ingress 列表的效果是相加的。

网络策略是相加的,所以不会产生冲突。如果策略适用于 Pod 某一特定方向的流量, Pod 在对应方向所允许的连接是适用的网络策略所允许的集合。 因此,评估的顺序不影响策略的结果。

要允许从源 Pod 到目的 Pod 的连接,源 Pod 的出口策略和目的 Pod 的入口策略都需要允许连接。 如果任何一方不允许连接,建立连接将会失败。

5.2NetworkPolicy 配置说明
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:			# 策略类型
    - Ingress			# 入站
    - Egress			# 出站
  ingress:			# 定义入栈内容
    - from:			# ingres from策略,以下策略是累加的,需同时满足才可访问
        - ipBlock:		# ip策略
            cidr: 172.17.0.0/16
            except:		# 排除地址
              - 172.17.1.0/24
        - namespaceSelector:	# namespace策略
            matchLabels:
              project: myproject
        - podSelector:		# pod策略
            matchLabels:
              role: frontend
      ports:			# 端口策略
        - protocol: TCP		# 端口类型
          port: 6379		# 端口号
  egress:			# 定义出站内容
    - to:			# egress to策略
        - ipBlock:
            cidr: 10.0.0.0/24
      ports:
        - protocol: TCP
          port: 5978

必需字段:与所有其他的 Kubernetes 配置一样,NetworkPolicy 需要 apiVersionkindmetadata 字段。

spec:NetworkPolicy 规约 中包含了在一个namespace中定义特定网络策略所需的所有信息。

podSelector:每个 NetworkPolicy 都包括一个 podSelector, 它对该策略所适用的一组 Pod 进行选择。示例中的策略选择带有 role=db 标签的 Pod。 空的 podSelector 选择名字空间下的所有 Pod。

policyTypes:每个 NetworkPolicy 都包含一个 policyTypes 列表,其中包含 IngressEgress 或两者兼具。policyTypes 字段表示给定的策略是应用于进入所选 Pod 的入站流量还是来自所选 Pod 的出站流量,或两者兼有。 如果 NetworkPolicy 未指定 policyTypes 则默认情况下始终设置 Ingress; 如果 NetworkPolicy 有任何出口规则的话则设置 Egress

ingress:每个 NetworkPolicy 可包含一个 ingress 规则的白名单列表。 每个规则都允许同时匹配 fromports 部分的流量。示例策略中包含一条简单的规则: 它匹配某个特定端口,来自三个来源中的一个,第一个通过 ipBlock 指定,第二个通过 namespaceSelector 指定,第三个通过 podSelector 指定。

egress:每个 NetworkPolicy 可包含一个 egress 规则的白名单列表。 每个规则都允许匹配 toport 部分的流量。该示例策略包含一条规则, 该规则将指定端口上的流量匹配到 10.0.0.0/24 中的任何目的地。

所以,该网络策略示例:

  1. 隔离 default 名字空间下 role=db 的 Pod (如果它们不是已经被隔离的话)。
  2. (Ingress 规则)允许以下 Pod 连接到 default 名字空间下的带有 role=db 标签的所有 Pod 的 6379 TCP 端口:
    • default 名字空间下带有 role=frontend 标签的所有 Pod
    • 带有 project=myproject 标签的所有名字空间中的 Pod
    • IP 地址范围为 172.17.0.0–172.17.0.255 和 172.17.2.0–172.17.255.255 (即,除了 172.17.1.0/24 之外的所有 172.17.0.0/16)
  3. (Egress 规则)允许 default 名字空间中任何带有标签 role=db 的 Pod 到 CIDR 10.0.0.0/24 下 5978 TCP 端口的连接。
5.3 选择器 tofrom

可以在 ingressfrom 部分或 egressto 部分中指定四种选择器:

podSelector:此选择器将在与 NetworkPolicy 相同的名字空间中选择特定的 Pod,应将其允许作为入站流量来源或出站流量目的地。

namespaceSelector:此选择器将选择特定的名字空间,应将所有 Pod 用作其入站流量来源或出站流量目的地。

namespaceSelector 和 podSelector:一个指定 namespaceSelectorpodSelectorto/from 条目选择特定名字空间中的特定 Pod。 注意使用正确的 YAML 语法;下面的策略:

  ...
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          user: alice
      podSelector:
        matchLabels:
          role: client
  ...

此策略在 from 数组中仅包含一个元素,只允许来自标有 role=client 的 Pod 且该 Pod 所在的namespace中标有 user=alice 的连接。但是这项策略:

  ...
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          user: alice
    - podSelector:
        matchLabels:
          role: client
  ...

它在 from 数组中包含两个元素,允许来自本地namespace中标有 role=client 的 Pod 的连接,或来自任何名字空间中标有 user=alice 的任何 Pod 的连接。

如有疑问,请使用 kubectl describe 查看 Kubernetes 如何解释该策略。

ipBlock:此选择器将选择特定的 IP CIDR 范围以用作入站流量来源或出站流量目的地。 这些应该是集群外部 IP,因为 Pod IP 存在时间短暂的且随机产生。

集群的入站和出站机制通常需要重写数据包的源 IP 或目标 IP。 在发生这种情况时,不确定在 NetworkPolicy 处理之前还是之后发生, 并且对于网络插件、云提供商、Service 实现等的不同组合,其行为可能会有所不同。

对入站流量而言,这意味着在某些情况下,你可以根据实际的原始源 IP 过滤传入的数据包, 而在其他情况下,NetworkPolicy 所作用的 源IP 则可能是 LoadBalancer 或 Pod 的节点等。

对于出站流量而言,这意味着从 Pod 到被重写为集群外部 IP 的 Service IP 的连接可能会或可能不会受到基于 ipBlock 的策略的约束。

5.4 默认策略

默认情况下,如果命名空间中不存在任何策略,则所有进出该命名空间中 Pod 的流量都被允许。 以下示例可以更改该命名空间中的默认行为。

5.4.1 默认拒绝所有入站流量

可以通过创建选择所有容器但不允许任何进入这些容器的入站流量的 NetworkPolicy 来为命名空间创建 “default” 隔离策略。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress

这确保即使没有被任何其他 NetworkPolicy 选择的 Pod 仍将被隔离以进行入口。 此策略不影响任何 Pod 的出口隔离。

5.4.2 允许所有入站流量

如果想允许一个名字空间中所有 Pod 的所有入站连接,可以创建一个明确允许的策略。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
spec:
  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress

有了这个策略,任何额外的策略都不会导致到这些 Pod 的任何入站连接被拒绝。 此策略对任何 Pod 的出口隔离没有影响。

5.4.3 默认拒绝所有出站流量

可以通过创建选择所有容器但不允许来自这些容器的任何出站流量的 NetworkPolicy 来为名字空间创建 “default” 隔离策略。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress

此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许流出流量。 此策略不会更改任何 Pod 的入站流量隔离行为。

5.4.4 允许所有出站流量

如果要允许来自命名空间中所有 Pod 的所有连接, 则可以创建一个明确允许来自该名字空间中 Pod 的所有出站连接的策略。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-egress
spec:
  podSelector: {}
  egress:
  - {}
  policyTypes:
  - Egress

有了这个策略,任何额外的策略都不会导致来自这些 Pod 的任何出站连接被拒绝。 此策略对进入任何 Pod 的隔离没有影响。

5.4.5 默认拒绝所有入站和所有出站流量

可以为命名空间创建“默认”策略,以通过在该名字空间中创建以下 NetworkPolicy 来阻止所有入站和出站流量。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许入站或出站流量。

‍5.5示例
5.5.1 ingress-以pod为限制单位,只允许同ns含有特定标签的源pod访问目标pod的所有端口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: python-tomcat-app1-selector #对匹配到的目的Pod应用以下规则
  ingress: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
  - from:
    - podSelector:
        matchLabels:
          #app: python-nginx-selector #如果存在多个matchLabel条件,如果存在多个matchLabel条件,是and的关系,即要同时满足条件A、条件B、条件X
          project: "python"
  • 不允许从其他namespace访问目标pod,即默认禁止了跨ns访问目标pod

从default中的访问也会被禁止

[root@net-test /]# curl 10.68.195.166/app/index.jsp
curl: (7) Failed connect to 10.68.195.166:80; Connection timed out

  • 非明确允许的pod,同namespace也无法访问

  • 不允许从宿主机访问目标pod

  • 该策略只允许同namespace含有特定标签的源pod访问目标pod,比如tomcat只允许有特定标签的源pod nginx访问

  • 该策略不影响其它ns的pod内部之间的相互访问,即linux的pod内部相互可以访问

  • 该策略不影响各ns的pod与非明确禁止的pod之间的访问,即linux的pod访问python的其他pod也正常。

5.5.2 ingress以pod加端口为限制单位、只允许同ns含有特定标签的源pod访问目标pod的指定端口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: python-tomcat-app1-selector
  ingress:
  - from:
    - podSelector:
        matchLabels:
          #app: python-nginx-selector #指定访问源的匹配条件,如果存在多个matchLabel条件,是and的关系,即要同时满足条件A、条件B、条件X
          project: "python"
    ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
      #port: 80

5.5.3 ingress 允许同namespace的所有pod访问当前ns的目标pod多个指定端口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access-networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector: #目标pod
    matchLabels:
      app: python-tomcat-app1-selector
  ingress:
  - from:
    - podSelector: #匹配源pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
        matchLabels: {}
    ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
      #port: 80
    - protocol: TCP
      port: 3306
    - protocol: TCP
      port: 6379

  • 跨ns禁止访问

linux ns 访问不了 python ns中的pod

  • 同ns的其它pod都可以访问指定目标端口(含多目标端口)
root@k8s-master1:/opt/dockerfile/k8s-data/NetWorkPolicy-case/python-ns2# kubectl exec -it -n python net-test bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
[root@net-test /]# curl -I 172.20.38.21/app
^C
[root@net-test /]# curl -I 172.20.38.21:8080/app
HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Tue, 18 Apr 2023 09:48:15 GMT

拒绝访问的iptables规则,只能在pod所在宿主机中查看

-A cali-pi-_0JuoNaejpHrnq9ok3ft -p tcp -m comment --comment "cali:qEZjDE_j-MWialKp" -m set --match-set cali40s:i_4-mErXOxx3I3EQOxm4JCQ src -m multiport --dports 3306,6379,8080 -j MARK --set-xmark 0x10000/0x10000
5.5.4 ingress 允许同namespace的所有pod访问当前ns的目标Pod所有端口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector: #目标pod
    matchLabels: {} #匹配所有目标pod
  ingress:
  - from:
    - podSelector: #匹配源pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
        matchLabels: {}

  • 其他ns无法访问目标ns的pod
  • 同ns的pod可以访问当前ns中的所有pod的任意端口
5.5.5 ingress-ipBlock白名单
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector: #目标pod
    matchLabels:
      app: python-tomcat-app1-selector
  ingress:
  - from:
#    - podSelector: #匹配源pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
#        matchLabels: {}
    - ipBlock:
        cidr: 172.20.0.0/16 #白名单,允许访问的地址范围,没有允许的将禁止访问目标pod
        except:
        - 172.20.169.137/32 #在以上范围内禁止访问的源IP地址
        - 172.20.108.176/32 #在以上范围内禁止访问的源IP地址
    ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
      #port: 80
    - protocol: TCP
      port: 3306
    - protocol: TCP
      port: 6379
  • 只要在白名单范围内没有被except指定禁止的源pod IP,都允许访问

在linux的ns下也可以访问python ns的目标Pod

root@k8s-master1:/opt/dockerfile/k8s-data/NetWorkPolicy-case/python-ns2# kubectl exec -it -n linux linux-nginx-deployment-864bcf5f4c-jhsdn sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # curl -I 172.20.38.21/app
^C
/ # curl -I 172.20.38.21:8080/app
HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Tue, 18 Apr 2023 10:28:58 GMT
  • 在只设置了ipBlock匹配的前提下,其它ns中没有在except范围的pod,也可以访问目标pod
5.5.6 ingress-namespace Selector-ns选择器
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector: #目标pod
    matchLabels: {} #允许访问python namespace 中的所有pod
#      app: python-tomcat-app1-selector #可以只允许访问python namespace中指定的pod
  ingress:
  - from:
#    - podSelector: #匹配源pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
#        matchLabels: {}
#    - ipBlock:
#        cidr: 10.200.0.0/16 #指定禁止访问的源网段
#        except:
#        - 10.200.218.0/24 #在以上范围内禁止访问的源IP地址

    - namespaceSelector:
#        matchLabels: {} #允许所有namespace访问python namespace指定的目标端口或指定的pod加指定端口
        matchLabels:
          nsname: linux #只允许指定的namespace访问
    - namespaceSelector:
        matchLabels:
          nsname: python #只允许指定的namespace访问
    ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
      #port: 80
    - protocol: TCP
      port: 3306
    - protocol: TCP
      port: 6379

在ns上打上相应的标签

kubectl label ns linux nsname=linux

kubectl label ns python nsname=python

  • 被明确允许的ns中的pod可以访问目标pod
  • 没有明确声明允许的ns将禁止访问
  • 没有明确声明允许的话,即使用同一个ns也禁止访问
  • 如只允许linux和python两个ns,则default中的pod将无法访问
5.5.7 Egress-podSelector-Pod出口方向目的IP及目的端口限制-只允许访问指定的目的地址范围及端口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-access-networkpolicy
  namespace: python
spec:
  policyTypes:
  - Egress
  podSelector: #目标pod选择器
    matchLabels:  #基于label匹配目标pod
      app: python-tomcat-app1-selector #匹配python namespace中app的值为python-tomcat-app1-selector的pod,然后基于egress中的指定网络策略进行出口方向的网络限制
  egress:
  - to:
    - ipBlock:
        cidr: 10.200.0.0/16 #允许匹配到的pod出口访问的目的CIDR地址范围
    - ipBlock:
        cidr: 172.31.7.106/32 #允许匹配到的pod出口访问的目的主机
    - ipBlock:
        cidr: 0.0.0.0/0 #允许匹配到的pod出口访问的目的主机
    ports:
    - protocol: TCP
      port: 80 #允许匹配到的pod访问目的端口为80的访问
    - protocol: TCP
      port: 53 #允许匹配到的pod访问目的端口为53 即DNS的解析
    - protocol: UDP
      port: 53 #允许匹配到的pod访问目的端口为53 即DNS的解析
  • 基于Egress白名单,定义ns中匹配成功的pod可以访问ipBlock指定的地址和ports指定的端口
  • 匹配成功的pod访问未明确定义的Egress的白名单和其它IP的请求,将拒绝
  • 没有匹配成功的源pod,主动发起的出口访问请求不受影响

由于只放开了53端口,可以看到,只能解析不能ping通baidu

kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@python-tomcat-app1-deployment-7bf9bb6989-gvbwz:/usr/local/tomcat# ping www.baidu.com
PING www.a.shifen.com (110.242.68.4) 56(84) bytes of data.
^C
--- www.a.shifen.com ping statistics ---

5.5.8 Egress-podSelector-Pod出口方向目的Pod限制-只允许访问指定的pod及端口

基于podSelector选择器,限制源pod能够访问的目的pod

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-access-networkpolicy
  namespace: python
spec:
  policyTypes:
  - Egress
  podSelector: #目标pod选择器
    matchLabels:  #基于label匹配目标pod
      app: python-nginx-selector #匹配python namespace中app的值为python-tomcat-app1-selector的pod,然后基于egress中的指定网络策略进行出口方向的网络限制
  egress:
  - to:
#    - ipBlock:
#        cidr: 10.200.0.0/16 #允许访问的目的CIDR地址范围
#    - ipBlock:
#        cidr: 172.31.7.106/32 #允许访问的目的主机地址
#    - ipBlock:
#        cidr: 10.200.218.4/32 #白名单,允许访问的目的主机地址
    - podSelector: #匹配pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
        matchLabels:
          app: python-tomcat-app1-selector
    ports:
    - protocol: TCP
      port: 8080 #允许80端口的访问
    - protocol: TCP
      port: 53 #允许DNS的解析
    - protocol: UDP
      port: 53


  • 匹配成功的源pod只能访问指定的目的pod的指定端口
  • 其它没有允许的出口请求将禁止访问
/ # curl -I 172.20.37.213:8080
HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Wed, 19 Apr 2023 09:21:20 GMT

/ # ping www.baidu.com
^C
/ # curl 172.20.38.55:8080
curl: (28) Failed to connect to 172.20.38.55 port 8080 after 131055 ms: Operation timed out
5.5.9 Egress-namespaceSelector
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-access-networkpolicy
  namespace: python
spec:
  policyTypes:
  - Egress
  podSelector: #目标pod选择器
    matchLabels:  #基于label匹配目标pod
      app: python-nginx-selector #匹配python namespace中app的值为python-tomcat-app1-selector的pod,然后基于egress中的指定网络策略进行出口方向的网络限制
  egress:
  - to:
#    - ipBlock:
#        cidr: 10.200.0.0/16 #允许访问的目的CIDR地址范围
#    - ipBlock:
#        cidr: 172.31.7.106/32 #允许访问的目的主机地址
#    - ipBlock:
#        cidr: 10.200.218.4/32 #允许访问的目的主机地址
#    - podSelector: #匹配pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
#        matchLabels:
#          app: python-tomcat-app1-selector

    - namespaceSelector:
        matchLabels:
          nsname: python #指定允许访问的目的namespace
    - namespaceSelector:
        matchLabels:
          nsname: linux #指定允许访问的目的namespace
    ports:
    - protocol: TCP
      port: 8080 #允许80端口的访问
    - protocol: TCP
      port: 53 #允许DNS的解析
    - protocol: UDP
      port: 53

限制匹配成功的pod没有访问指定的namespace

  • 匹配成功的源pod可以访问指定的目标namespace
  • 不能访问除指定的namespaces以外的其它namespace及外网
  • 比如允许指定的源pod访问linux和python ns中的8080,53
root@k8s-master1:/opt/dockerfile/k8s-data/NetWorkPolicy-case/python-ns2# kubectl exec -it python-nginx-deployment-5c658bf86b-vg6vl -n python sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # curl -I 172.20.37.213:8080
HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Wed, 19 Apr 2023 09:38:35 GMT

/ # curl -I 172.20.38.55:8080
HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Wed, 19 Apr 2023 09:39:00 GMT

/ # ping www.baidu.com
^C
/ # 

六、ingress使用总结

https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/

6.1 ingress简介

Ingress是kubernetes内置的一个资源对象,是kubernetes集群外部访问集群的一个入口,将外部的请求转发到不同的service上,其实就是相当nginx和haproxy等负载均衡代理服务器。Ingress将集群外部的请求资源转发到集群内部的service,service再将请求转发至pod。

img

Ingress 可为 Service 提供外部可访问的 URL、负载均衡流量、 SSL/TLS终止,以及基于名称的虚拟主机。 Ingress 控制器 通常负责通过负载均衡器来实现 Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。

Ingress 不会公开任意端口或协议。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePortService.Type=LoadBalancer 类型的 Service

6.2部署ingress-nginx控制器

为了让 Ingress 资源工作,集群必须有一个正在运行的 Ingress 控制器。与作为 kube-controller-manager 可执行文件的一部分运行的其他类型的控制器不同, Ingress 控制器不是随集群自动启动的。

Kubernetes 目前支持和维护 AWS、 GCE 和 Nginx Ingress 控制器。通常使用nginx-ingress作为控制器,它使用NGINX服务器作为反向代理来把流量路由给后面的Service

https://github.com/kubernetes/ingress-nginx/blob/main/README.md#readme

https://kubernetes.github.io/ingress-nginx/deploy/

  1. 下载yaml文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/cloud/deploy.yaml

2.下载镜像并上传至harbor仓库

 grep 'image:' deploy.yaml
        image: registry.k8s.io/ingress-nginx/controller:v1.5.1@sha256:4ba73c697770664c1e00e9f968de14e08f606ff961c76e5d7033a4a9c593c629
        image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f

谷歌镜像无法下载,下载个人镜像

nerdctl pull anjia0532/google-containers.ingress-nginx.controller:v1.5.1

nerdctl pull anjia0532/google-containers.ingress-nginx.kube-webhook-certgen:v20220916-gd32f8c343

打tag

nerdctl tag anjia0532/google-containers.ingress-nginx.controller:v1.5.1 harbor.jackedu.net/baseimage/ingress-nginx.controller:v1.5.1

上传至harbor仓库

nerdctl push harbor.jackedu.net/baseimage/ingress-nginx.controller:v1.5.1

nerdctl push harbor.jackedu.net/baseimage/kube-webhook-certgen:v20220916-gd32f8c343

修改yaml文件中镜像地址

grep "image:" deploy.yaml
image: harbor.jackedu.net/baseimage/ingress-nginx.controller:v1.5.1
image: harbor.jackedu.net/baseimage/kube-webhook-certgen:v20220916-gd32f8c343
image: harbor.jackedu.net/baseimage/kube-webhook-certgen:v20220916-gd32f8c343

将ingress-nginx-controller service中type由LoadBalancer修改为NodePort,第381行

type: NodePort

3.创建ingress控制器

root@k8s-master1:/opt/dockerfile/k8s-data/ingress-nginx# kubectl apply -f deploy.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

4.验证

root@k8s-master1:/opt/dockerfile/k8s-data/ingress-nginx# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-7vfpv 0/1 Completed 0 63s
ingress-nginx-admission-patch-tnfq6 0/1 Completed 1 63s
ingress-nginx-controller-f7cb888c9-fcz22 1/1 Running 0 63s
root@k8s-master1:/opt/dockerfile/k8s-data/ingress-nginx# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.68.204.187 80:39596/TCP,443:57911/TCP 75s
ingress-nginx-controller-admission ClusterIP 10.68.75.40 443/TCP 75s

6.3 Ingress资源

6.3.1 Ingress规则
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations: 				# 注解,表示把ingress的资源通知给哪个类别的ingress controller
    nginx.ingress.kubernetes.io/rewrite-target: / # 重写目标注解
spec:
  rules:		 		# 里面主要字段就只有host和http
  - host: www.test.com			# 用于指定虚拟主机的名称,如果不写将匹配任意名称
    http:				# http用来定义指向后端的http选择器列表,其值为一个对象,里面只有一个paths
      paths:				# paths字段用于把请求映射到后端的某个路径,其值为一个对象列表
      - path: /testpath			# 定义path来指定映射后端的路径 
        pathType: Prefix		# 路径类型
        backend:			# backend用于指定后端pod的service,其值为一个对象
          service:			# 定义后端service
            name: test			# service名称
            port:			# 端口
              number: 80		# 端口号80

Ingress 需要指定 apiVersionkindmetadataspec 字段。 Ingress 对象的命名必须是合法的 DNS 子域名名称。

Ingress 经常使用注解(annotations)来配置一些选项,具体取决于 Ingress 控制器,例如重写目标注解。 不同的 Ingress 控制器支持不同的注解。

Ingress 规约 提供了配置负载均衡器或者代理服务器所需的所有信息。 最重要的是,其中包含与所有传入请求匹配的规则列表。 Ingress 资源仅支持用于转发 HTTP(S) 流量的规则。

每个 HTTP 规则都包含以下信息:

  • 可选 host。在此示例中,未指定 host,该规则适用于通过指定 IP 地址的所有入站 HTTP 通信。 如果提供了 host(例如 foo.bar.com),则 rules 适用于该 host
  • 路径列表(例如 /testpath),每个路径都有一个由 service.nameservice.port.nameservice.port.number 定义的关联后端。 在负载均衡器将流量定向到引用的服务之前,主机和路径都必须匹配传入请求的内容。
  • backend(后端)是 Service 文档中所述的服务和端口名称的组合, 或者是通过 CRD 方式来实现的自定义资源后端。 与规则的 hostpath 匹配的对 Ingress 的 HTTP(和 HTTPS )请求将发送到列出的 backend

通常在 Ingress 控制器中会配置 defaultBackend(默认后端),以服务于无法与规约中 path 匹配的所有请求。

6.3.2默认后端

没有设置规则的 Ingress 将所有流量发送到同一个默认后端,而 .spec.defaultBackend 则是在这种情况下处理请求的那个默认后端。 defaultBackend 通常是 Ingress 控制器的配置选项, 而非在 Ingress 资源中指定。 如果未设置任何的 .spec.rules,那么必须指定 .spec.defaultBackend。 如果未设置 defaultBackend,那么如何处理所有与规则不匹配的流量将交由 Ingress 控制器决定。

6.3.3资源后端

Resource 后端是一个引用,指向同一命名空间中的另一个 Kubernetes 资源,将其作为 Ingress 对象。

Resource 后端与 Service 后端是互斥的,在二者均被设置时会无法通过合法性检查。 Resource 后端的一种常见用法是将所有入站数据导向带有静态资产的对象存储后端。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-resource-backend
spec:
  defaultBackend:
    resource:
      apiGroup: k8s.example.com
      kind: StorageBucket
      name: static-assets
  rules:
    - http:
        paths:
          - path: /icons
            pathType: ImplementationSpecific
            backend:
              resource:
                apiGroup: k8s.example.com
                kind: StorageBucket
                name: icon-assets
6.3.4 PathType

Ingress 中的每个路径都需要有对应的路径类型(PathType)。未明确设置 pathType 的路径无法通过合法性检查。当前支持的路径类型有三种:

  • ImplementationSpecific:对于该路径类型,匹配方法取决于 IngressClass。 具体实现可以将其作为单独的 pathType 处理或者与 PrefixExact 类型作相同处理。
  • Exact:精确匹配 URL 路径,且区分大小写。
  • Prefix:基于以 / 分隔的 URL 路径前缀匹配。匹配区分大小写,并且对路径中的元素逐个完成。 路径元素指的是由 / 分隔符分隔的路径中的标签列表。 如果每个 p 都是请求路径 p 的元素前缀,则请求与路径 p 匹配。

说明: 如果路径的最后一个元素是请求路径中最后一个元素的子字符串,则不会匹配 (例如:/foo/bar 匹配 /foo/bar/baz, 但不匹配 /foo/barbaz)。

6.3.5 匹配规则
类型 路径 请求路径 匹配与否
Prefix / (所有路径)
Exact /foo /foo
Exact /foo /bar
Exact /foo /foo/
Exact /foo/ /foo
Prefix /foo /foo, /foo/
Prefix /foo/ /foo, /foo/
Prefix /aaa/bb /aaa/bbb
Prefix /aaa/bbb /aaa/bbb
Prefix /aaa/bbb/ /aaa/bbb 是,忽略尾部斜线
Prefix /aaa/bbb /aaa/bbb/ 是,匹配尾部斜线
Prefix /aaa/bbb /aaa/bbb/ccc 是,匹配子路径
Prefix /aaa/bbb /aaa/bbbxyz 否,字符串前缀不匹配
Prefix /, /aaa /aaa/ccc 是,匹配 /aaa 前缀
Prefix /, /aaa, /aaa/bbb /aaa/bbb 是,匹配 /aaa/bbb 前缀
Prefix /, /aaa, /aaa/bbb /ccc 是,匹配 / 前缀
Prefix /aaa /ccc 否,使用默认后端
混合 /foo (Prefix), /foo (Exact) /foo 是,优选 Exact 类型

多重匹配

在某些情况下,Ingress 中的多条路径会匹配同一个请求。 这种情况下最长的匹配路径优先。 如果仍然有两条同等的匹配路径,则精确路径类型优先于前缀路径类型。

6.3.6 主机名通配符

主机名可以是精确匹配(例如 foo.bar.com)或者使用通配符来匹配 (例如 *.foo.com)。 精确匹配要求 HTTP host 头部字段与 host 字段值完全匹配。 通配符匹配则要求 HTTP host 头部字段与通配符规则中的后缀部分相同。

主机 host 头部 匹配与否
*.foo.com bar.foo.com 基于相同的后缀匹配
*.foo.com baz.bar.foo.com 不匹配,通配符仅覆盖了一个 DNS 标签
*.foo.com foo.com 不匹配,通配符仅覆盖了一个 DNS 标签
6.4 准备环境
6.4.1 下载镜像,并上传至harbor仓库

nerdctl pull nginx:mainline-alpine-slim
nerdctl tag nginx:mainline-alpine-slim harbor.jackedu.net/app/nginx:mainline-alpine-slim
erdctl push harbor.jackedu.net/app/nginx:mainline-alpine-slim

6.4.2编写yaml
kind: Pod
apiVersion: v1
metadata:
  name: annie-app
  namespace: test
  labels:
    app: annie
spec:
  containers:
  - name: annie-app
    image: harbor.jackedu.net/app/nginx:mainline-alpine-slim
    ports:
    - containerPort: 80
  
---
kind: Service
apiVersion: v1
metadata:
  name: annie-service
  namespace: test
spec:
  selector:
    app: annie
  ports:
  - port: 8080
    targetPort: 80
---
kind: Pod
apiVersion: v1
metadata:
  name: lily-app
  namespace: test
  labels:
    app: lily
spec:
  containers:
  - name: lily-app
    image: harbor.jackedu.net/app/nginx:mainline-alpine-slim
    ports:
    - containerPort: 80
 
---
kind: Service
apiVersion: v1
metadata:
  name: lily-service
  namespace: test
spec:
  selector:
    app: lily
  ports:
  - port: 8080
    targetPort: 80
---

6.4.3 创建服务
kubectl apply -f nginx-demo.yaml

root@k8s-master1:/opt/dockerfile/k8s-data/ingress-nginx# kubectl get svc -n test
NAME                       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
annie-service              ClusterIP   10.68.138.20    <none>        8080/TCP                     7m23s
lily-service               ClusterIP   10.68.94.225    <none>        8080/TCP                     6s
magedu-nginx-service       NodePort    10.68.50.115    <none>        80:30333/TCP                 43d
magedu-wordpress-service   NodePort    10.68.147.151   <none>        80:30133/TCP                 43d
python-nginx-service       NodePort    10.68.14.164    <none>        80:30014/TCP,443:30453/TCP   24d
server-app-frontend        ClusterIP   None            <none>        80/TCP                       70d
root@k8s-master1:/opt/dockerfile/k8s-data/ingress-nginx# kubectl get po -n test
NAME         READY   STATUS      RESTARTS   AGE
annie-app    1/1     Running     0          13m
lily-app     1/1     Running     0          13m
ubuntu1804   0/1     Completed   0          55d

6.4.4 准备页面
root@k8s-master1:/opt/dockerfile/k8s-data/ingress-nginx# kubectl exec -it -n test annie-app sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo "annie-app" > /usr/share/nginx/html/index.html
/ # exit
root@k8s-master1:/opt/dockerfile/k8s-data/ingress-nginx# kubectl exec -it -n test lily-app sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo "lily-app"  > /usr/share/nginx/html/index.html

6.4.5验证service

进入容器,访问测试

[root@net-test /]# curl annie-service.test.svc:8080
annie-app
[root@net-test /]# curl lily-service.test.svc:8080
lily-app

6.5 实现虚拟主机

基于客户端请求的host域名进行转发

6.5.1 单虚拟主机

编写yaml文件

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-web
  namespace: test
  annotations:
    kubernetes.io/ingress.class: "nginx" 			#指定Ingress Controller的类型
    nginx.ingress.kubernetes.io/use-regex: "true"		#指定后面rules定义的path可以使用正则表达式
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"	#连接超时时间,默认为5s
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600" 	#后端服务器回转数据超时时间,默认为60s
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600" 	#后端服务器响应超时时间,默认为60s
    nginx.ingress.kubernetes.io/proxy-body-size: "50m" 		#客户端上传文件,最大大小,默认为20m
    #nginx.ingress.kubernetes.io/rewrite-target: / 		#URL重写
    nginx.ingress.kubernetes.io/app-root: /index.html
spec:
  rules:
  - host: www.myapp.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: annie-service 
            port:
              number: 8080

查看

kubectl get ingress -n test
NAME        CLASS    HOSTS           ADDRESS         PORTS   AGE
nginx-web   <none>   www.myapp.com   10.68.204.187   80      5d19h

验证

6.5.2 多虚拟主机

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-web
  namespace: test
  annotations:
    kubernetes.io/ingress.class: "nginx" 		##指定Ingress Controller的类型
    nginx.ingress.kubernetes.io/use-regex: "true" 	##指定后面rules定义的path可以使用正则表达式
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" 	##连接超时时间,默认为5s
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600" 	##后端服务器回转数据超时时间,默认为60s
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600" 	##后端服务器响应超时时间,默认为60s
    nginx.ingress.kubernetes.io/proxy-body-size: "10m" 		##客户端上传文件,最大大小,默认为20m
    #nginx.ingress.kubernetes.io/rewrite-target: / 		##URL重写
    nginx.ingress.kubernetes.io/app-root: /index.html
spec:
  rules:
  - host: www.annie.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: annie-service
            port:
              number: 8080
  - host: www.lily.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: lily-service 
            port:
              number: 8080

查看状态

root@k8s-master1:/opt/dockerfile/k8s-data/ingress-nginx# kubectl describe ingress -n test nginx-web 
Name:             nginx-web
Labels:           <none>
Namespace:        test
Address:          10.68.204.187
Ingress Class:    <none>
Default backend:  <default>
Rules:
  Host           Path  Backends
  ----           ----  --------
  www.annie.com  
                 /   annie-service:8080 (172.20.38.55:80)
  www.lily.com   
                 /   lily-service:8080 (172.20.38.60:80)
Annotations:     kubernetes.io/ingress.class: nginx
                 nginx.ingress.kubernetes.io/app-root: /index.html
                 nginx.ingress.kubernetes.io/proxy-body-size: 10m
                 nginx.ingress.kubernetes.io/proxy-connect-timeout: 600
                 nginx.ingress.kubernetes.io/proxy-read-timeout: 600
                 nginx.ingress.kubernetes.io/proxy-send-timeout: 600
                 nginx.ingress.kubernetes.io/use-regex: true
Events:
  Type    Reason  Age                      From                      Message
  ----    ------  ----                     ----                      -------
  Normal  Sync    <invalid> (x2 over 63m)  nginx-ingress-controller  Scheduled for sync

验证

访问annie.com

lily.com

6.5.3 其他

如果创建的 Ingress 资源没有在 rules 中定义的任何 hosts,则可以匹配指向 Ingress 控制器 IP 地址的任何网络流量,而无需基于名称的虚拟主机。

例如,以下 Ingress 会将请求 first.bar.com 的流量路由到 service1,将请求 second.bar.com 的流量路由到 service2,而所有其他流量都会被路由到 service3

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: name-virtual-host-ingress-no-third-host
spec:
  rules:
  - host: first.bar.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service1
            port:
              number: 80
  - host: second.bar.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service2
            port:
              number: 80
  - http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service3
            port:
              number: 80
6.6 实现URL转发

根据客户端请求的同一host不同的URL进行转发

查看状态

Name:             nginx-web
Labels:           <none>
Namespace:        test
Address:          10.68.204.187
Ingress Class:    <none>
Default backend:  <default>
Rules:
  Host           Path  Backends
  ----           ----  --------
  www.myapp.com  
                 /annie   annie-service:8080 (172.20.38.55:80)
                 /lily    lily-service:8080 (172.20.38.60:80)
Annotations:     kubernetes.io/ingress.class: nginx
                 nginx.ingress.kubernetes.io/app-root: /index.html
                 nginx.ingress.kubernetes.io/proxy-body-size: 10m
                 nginx.ingress.kubernetes.io/proxy-connect-timeout: 600
                 nginx.ingress.kubernetes.io/proxy-read-timeout: 600
                 nginx.ingress.kubernetes.io/proxy-send-timeout: 600
                 nginx.ingress.kubernetes.io/rewrite-target: /
                 nginx.ingress.kubernetes.io/use-regex: true
Events:
  Type    Reason  Age                  From                      Message
  ----    ------  ----                 ----                      -------
  Normal  Sync    2m30s (x3 over 90m)  nginx-ingress-controller  Scheduled for sync

浏览器验证

注意: .metadata.annotations 字段中添加URL重写属性nginx.ingress.kubernetes.io/rewrite-target: / www.myapp.com/foo/index.html路径将转发至后端foo-service/index.html,若不增加URL重写属性,将转发至后端foo-service/foo/index.html路径。

6.7 实现域名HTTPS

配置多域名HTTPS

6.7.1 创建secret
#创建ca
openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3560 -nodes -subj '/CN=www.ca.com'

# 创建www.annie.com域名证书,并用CA进行签名
openssl req -new -newkey rsa:4096 -keyout server_annie.key -out server_annie.csr -nodes -subj '/CN=www.annie.com'
openssl x509 -req -sha256 -days 3650 -in server_annie.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server_annie.crt

# 创建www.foo.com域名证书,并用CA进行签名
openssl req -new -newkey rsa:4096 -keyout server_lily.key -out server_lily.csr -nodes -subj '/CN=www.lily.com'
openssl x509 -req -sha256 -days 3650 -in server_lily.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server_lily.crt

#创建secret
kubectl create secret tls tls-secret-annie --cert=./server_annie.crt --key=./server_annie.key -n test
kubectl create secret tls tls-secret-lily --cert=./server_lily.crt --key=./server_lily.key -n test


验证

 kubectl describe secrets -n test
Name:         tls-secret-annie
Namespace:    test
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1667 bytes
tls.key:  3272 bytes


Name:         tls-secret-lily
Namespace:    test
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1663 bytes
tls.key:  3272 bytes

6.7.2 编写yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-https-web
  namespace: test
  annotations:
    kubernetes.io/ingress.class: "nginx" 	##指定Ingress Controller的类型
    nginx.ingress.kubernetes.io/ssl-redirect: 'true'
spec:
  tls:
  - hosts:
    - www.annie.com
    secretName: tls-secret-annie 
  - hosts:
    - www.lily.com
    secretName: tls-secret-lily
  rules:
  - host: www.annie.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: annie-service
            port:
              number: 8080
  - host: www.lily.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: lily-service
            port:
              number: 8080

查看状态

kubectl describe ingress -n test nginx-https-web 
Name:             nginx-https-web
Labels:           <none>
Namespace:        test
Address:          10.68.204.187
Ingress Class:    <none>
Default backend:  <default>
TLS:
  tls-secret-annie terminates www.annie.com
  tls-secret-lily terminates www.lily.com
Rules:
  Host           Path  Backends
  ----           ----  --------
  www.annie.com  
                 /   annie-service:8080 (172.20.38.55:80)
  www.lily.com   
                 /   lily-service:8080 (172.20.38.60:80)
Annotations:     kubernetes.io/ingress.class: nginx
                 nginx.ingress.kubernetes.io/ssl-redirect: true
Events:
  Type    Reason  Age                From                      Message
  ----    ------  ----               ----                      -------
  Normal  Sync    14m (x2 over 14m)  nginx-ingress-controller  Scheduled for sync

6.7.3 浏览器验证

注意:默认规则上无法使用 TLS,需要为所有可能的子域名发放证书。 因此,tls 字段中的 hosts 的取值需要与 rules 字段中的 host 完全匹配。

6.8 更新HTTPS证书
6.8.1 创建新证书
cd /data/certs
# 若没有CA证书,则执行新建证书命令
# openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3560 -nodes -subj '/CN=www.ca.com'
 
# 创建新www.annie.com域名证书
openssl req -new -newkey rsa:4096 -keyout server_annie.key -out server_annie.csr -nodes -subj '/CN=www.annie.com'
openssl x509 -req -sha256 -days 3650 -in server_annie.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server_annie.crt
 
#创建新www.lily.com域名证书
openssl req -new -newkey rsa:4096 -keyout server_lily.key -out server_lily.csr -nodes -subj '/CN=www.lily.com'
openssl x509 -req -sha256 -days 3650 -in server_lily.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server_lily.crt
6.8.2 创建新secret
kubectl create secret tls tls-secret-annie-update --cert=./server_foo.crt --key=./server_foo.key -n test
kubectl create secret tls tls-secret-lily-update --cert=./server_bar.crt --key=./server_bar.key -n test
 
# 查看新secret中tls.crt、tls.key值
[root@k8s-deploy certs]#kubectl get secret tls-secret-annie-update -n test  -oyaml
apiVersion: v1
data:
  tls.crt: LS0tLS1CRUdJ.....ZJQ0FURS0tLS0tCg==
  tls.key: LS0tLS1CRUdJTiBQUotL......lWQVRFIEtFWS0tLS0tCg==
kind: Secret
metadata:
  creationTimestamp: "2023-02-18T17:08:31Z"
  name: tls-secret-foo-update
  namespace: web
  resourceVersion: "2879019"
  uid: 0858588b-fd34-4205-916d-606fc718d780
type: kubernetes.io/tls
6.8.3 更新原secret
# 获取tls.crt、tls.key的值
[root@k8s-deploy ~]#kubectl get secret tls-secret-annie-update -n test -oyaml|grep tls.crt|awk '{print $2}'
LS0tLS1CRUdJTiBDRVJUSUZJQ0FU......HQTFVRUF3d0tkM2QzTG1OaExtTnYKYlRBZ
[root@k8s-deploy ~]#kubectl get secret tls-secret-annie-update -n test -oyaml|grep tls.key|awk '{print $2}'
LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRUUl......OXcVBQW9JQ0FRQzY3SjQ5eWk4bVQzM0oKVjU0e
 
# 编辑原secret,进行tls.crt、tls.key的值替换
kubectl edit secret tls-secret-annie -n test
# 操作与vi命令相同,替换tls.crt、tls.key的值后保存退出,证书自动更新
6.8.4 验证

标签:elk,ingress,网络,nginx,io,pod,k8s,Pod
From: https://www.cnblogs.com/jackwu81/p/17389022.html

相关文章

  • ALLEGRO用COP命令复制无属性过孔时自动添加过孔为GND网络或者其它电源网络
    1,COPY命令复制无属性的过孔步骤,下面FIND面板选择过孔,右边Options里的Retainnetofvias里勾去掉,如果要跟网络一起复制就勾上 按照图1里的操作,是无属性的过孔复制,但实际复制后是图2里的样子,过孔自动带了VCC3V3的网络,其实是因其它层有Shape铺铜VCC3V3的网络(这里做个注释,因为我......
  • 专属于AI的社交网络,全体人类被禁言只能围观
    玩腻了推特和微博?一个新的社交平台推荐给大家。这是一个名叫Chirper的社交网络,里面有成千上万的用户每日积极发帖,活跃度堪比ChatGPT。来自微博用户的分享Chirper社交网络内的分享热闹归热闹,只不过——没有一个是人类。不用怀疑,因为这个社区有一条神奇准则:Nohumansallowed,人类,禁止......
  • k8s认证、授权与准入控制
    KubernetesAPIServer是Kubernetes集群的控制中心,提供了KubernetesAPI的访问入口。为了保证Kubernetes集群的安全性,Kubernetes提供了许多APIServer访问控制机制,如下所示:认证(Authentication):APIServer可以支持多种身份认证方式,如证书、静态令牌、动态令牌(Token)和......
  • k8s 部署 elasticsearch 单节点
    es.yaml#pv和pvcapiVersion:v1kind:PersistentVolumemetadata:name:es-pvspec:capacity:storage:5GiaccessModes:-ReadWriteManypersistentVolumeReclaimPolicy:RetainstorageClassName:es-hosthostPath:path:/data/es-data---......
  • 《网络对抗技术》——Exp7 网络欺诈防范
    一、实践内容本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法。具体实践有:简单应用SET工具建立冒名网站ettercapDNSspoof结合应用两种技术,用DNSspoof引导特定访问到冒名网站请勿使用外部网站做实验二、实践原理EtterCapEtterCap是一款......
  • 无需代码绘制人工神经网络ANN模型结构图的方法
      本文介绍几种基于在线网页或软件的、不用代码的神经网络模型结构可视化绘图方法。  之前向大家介绍了一种基于Python第三方ann_visualizer模块的神经网络结构可视化方法,大家可以直接点击文章Python绘制神经网络模型图进行查看;这一方法可以对Dense隐藏层以及MaxPooling层、D......
  • PSO优化LSTM做时间序列的预测,优化的是隐藏层单元数目,批处理大小,时间窗口大小,学习率等
    PSO优化LSTM做时间序列的预测,优化的是隐藏层单元数目,批处理大小,时间窗口大小,学习率等网络参数。ID:1888668442690309......
  • k8s service资源
    在Kubernetes中,Service资源是一种抽象的逻辑概念,它定义了一组Pod的访问方式,为Pod提供稳定的DNS名称和IP地址,通过代理(Proxy)的方式向应用程序终端用户提供可靠的访问。Service资源对象提供了以下功能:为一组具有相同功能但可能在不同Pod或节点中的Pod提供一个稳定的虚拟IP地址和DN......
  • Kubernetes概述 (一篇教你认识k8s)
    一、Kubernetes概述 1.k8s是什么K8S的全称为Kubernetes(K12345678S),PS:“嘛,写全称也太累了吧,不如整个缩写”。作用:用于自动部署、扩展和管理“容器化(containerized)应用程序"的开源系统。可以理解成K8S是负责自动化运维管理多个容器化程序(比如Docker)的集群,是一......
  • 下篇:使用jenkins发布go项目到k8s,接上篇的手工体验改造为自动化发布
    写在开篇关于上篇本篇在 《上篇:带你手工体验从写代码、编译、打包镜像、部署到K8S的全过程》 的基础上,将手动的过程通过jenkins工具将其改造成自动化。环境准备我的环境说明:组件安装方式访问IP访问端口jenkinsdocker192.168.11.2548086gitlabdocker192......