主頁 >  其他 > kubernetes(十九) 網路

kubernetes(十九) 網路

2020-09-14 21:27:18 其他

前言

本文通過兩個簡單的服務之間的訪問,結合tcpdump抓包,詳細分析下在IPVS模式下,kubernetes實作通過服務名稱訪問NodePort、ClusterIp型別的service的原理,

當然kubernetes網路實作牽扯到很多知識,特別是對Linux低層的模塊的各種呼叫,如果對Linux中的網路命名空間、eth設備對、網橋等模塊不熟悉的話,可以先參考下另一篇文章[Docker 網路](Docker 網路.md),之后也可以看下另一篇檔案[Kubernetes kube-proxy](Kubernetes kube-proxy詳解.md)來了解下kube-proxy的IPVS模式

本文環境基于flannel網路插件,具體搭建參考kubernetes安裝-二進制

集群環境

角色 系統 CPU Core 記憶體 主機名稱 ip 安裝組件
master 18.04.1-Ubuntu 4 8G master 192.168.0.107 kubectl,kube-apiserver,kube-controller-manager,kube-scheduler,etcd,flannald,kubelet,kube-proxy
slave 18.04.1-Ubuntu 4 4G slave 192.168.0.114 docker,flannald,kubelet,kube-proxy,coredns

拓撲圖

節點路由資訊

  1. master節點

    $ route -n -v
    內核 IP 路由表
    目標            網關            子網掩碼        標志  躍點   參考  使用 介面
    0.0.0.0         192.168.0.1     0.0.0.0         UG    600    0        0 wlp3s0
    169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 wlp3s0
    172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-471858815e83
    172.30.22.0     0.0.0.0         255.255.255.0   U     0      0        0 docker0
    172.30.78.0     172.30.78.0     255.255.255.0   UG    0      0        0 flannel.1
    192.168.0.0     0.0.0.0         255.255.255.0   U     600    0        0 wlp3s0
    	
    
  2. slave節點

    route -v -n
    內核 IP 路由表
    目標            網關            子網掩碼        標志  躍點   參考  使用 介面
    0.0.0.0         192.168.0.1     0.0.0.0         UG    600    0        0 wlo1
    169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 wlo1
    172.30.22.0     172.30.22.0     255.255.255.0   UG    0      0        0 flannel.1
    172.30.78.0     0.0.0.0         255.255.255.0   U     0      0        0 docker0
    192.168.0.0     0.0.0.0         255.255.255.0   U     600    0        0 wlo1
    	
    

鏡像準備

  1. web鏡像

    用spring boot啟動了一個web服務,監聽8080埠,里面提供一個方法 /header/list,呼叫這個方法后,會把呼叫者地址相關資訊輸出出來

    @RequestMapping("/header/list")
    public String listHeader(HttpServletRequest request) {
    	
    	log.info("host is" + request.getHeader("host"));
    	
    	log.info("remoteAddr is " + request.getRemoteHost());
    	
    	log.info("remotePort is " + request.getRemotePort());
    	
    	return "OK";
    }
    
    
  2. curl鏡像

    基于 alpine鏡像,只安裝了一個curl命令,使我們可以通過這個命令訪問web服務

    FROM alpine:latest
    RUN apk update
    RUN apk add --upgrade curl
    
    

為節點添加label

為了控制pod啟動到指定的節點完成下面的分析,給兩個節點分別添加不同的label

$ kubectl label nodes master sample=master
node/master labeled
	
$ kubectl label nodes slave sample=slave
node/slave labeled
	

例子1

web服務的curl服務對應的pod都在master節點上,由拓撲圖可知,此次訪問通信只用經過master 節點上的docker0網橋即可實作

  1. 撰寫web服務啟動檔案

    $ cat > web.yml <<EOF
    apiVersion: v1
    kind: Service
    metadata:
      name: clientip
    spec:
            #type: NodePort
      selector:
        app: clientip
      ports:
      - name: http
        port: 8080
        targetPort: 8080
        #nodePort: 8086
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: clientip-deployment
    spec:
      selector:
        matchLabels:
          app: clientip
      replicas: 1
      template:
        metadata:
          labels:
            app: clientip
        spec:
          nodeSelector:
            sample: master
          containers:
          - name: clientip
            image: 192.168.0.107/k8s/client-ip-test:0.0.2
            ports:
            - containerPort: 8080
          
    EOF
         
    
  2. 撰寫啟動 curl pod的檔案

    $ cat > pod_curl.yml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: curl
    spec:
      containers:
      - name: curl
        image: 192.168.0.107/k8s/curl:1.0
        command:
          - sleep
          - "3600"
      nodeSelector:
        sample: master
    EOF
    	
    
  3. 啟動服務

    $ kubectl create -f web.yml -f pod_curl.yml
    	
    $ kubectl get pod -o wide
    NAME                                   READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
    clientip-deployment-5d8b5dcb46-qprps   1/1     Running   0          4s    172.30.22.4   master   <none>           <none>
    curl                                   1/1     Running   0          9s    172.30.22.3   master   <none>           <none>
    	
    $ kubectl get svc
    NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    clientip     ClusterIP   10.254.0.30   <none>        8080/TCP   51s
    kubernetes   ClusterIP   10.254.0.1    <none>        443/TCP    25d
    
    

    可以看到,兩個服務服務都正常啟動起來,并啟動在master節點上

  4. 啟動監聽master節點上docker0、flannel.1設備

    $ tcpdump -n -vv -i docker0
    	
    $ tcpdump -n -vv -i flannel.1 
    	
    
    1. 在curl 容器中訪問clientip 這個web服務
    $ kubectl exec -it curl curl http://clientip:8080/header/list
    OK
    	
    
  5. 監控日志分析

    1. web 服務日志

      2020-03-06 08:29:05.447  INFO 6 --- [nio-8080-exec-1] c.falcon.clientip.ClientIpController     : host isclientip:8080
      2020-03-06 08:29:05.447  INFO 6 --- [nio-8080-exec-1] c.falcon.clientip.ClientIpController     : remoteAddr is 172.30.22.3
      2020-03-06 08:29:05.447  INFO 6 --- [nio-8080-exec-1] c.falcon.clientip.ClientIpController     : remotePort is 42000
      	
      
      • 請求remoteAddr IP 172.30.22.3對應curl pod的IP地址
    2. docker0網路監控(只摘錄了主要流程的日志)

      172.30.22.3.47980 > 10.254.0.2.53: [bad udp cksum 0xcd6e -> 0xdae6!] 22093+ A? clientip.default.svc.cluster.local. (52) 
      ...
      	
      10.254.0.2.53 > 172.30.22.3.47980: [udp sum ok] 22093*- q: A? clientip.default.svc.cluster.local. 1/0/0 clientip.default.svc.cluster.local. A 10.254.0.30 (102)
      	
      ...
      	
      172.30.22.3.42000 > 10.254.0.30.8080: Flags [P.], cksum 0xcdbb (incorrect -> 0x95b1), seq 0:88, ack 1, win 507, options [nop,nop,TS val 3200284558 ecr 1892112994], length 88: HTTP, length: 88
      GET /header/list HTTP/1.1
      Host: clientip:8080
      User-Agent: curl/7.67.0
      Accept: */*
         
      ...
      172.30.22.3.42000 > 172.30.22.4.8080: Flags [P.], cksum 0x84c2 (incorrect -> 0xdeaa), seq 1:89, ack 1, win 507, options [nop,nop,TS val 3200284558 ecr 1892112994], length 88: HTTP, length: 88
      GET /header/list HTTP/1.1
      Host: clientip:8080
      User-Agent: curl/7.67.0
      Accept: */*
          
      ...
         
      172.30.22.4.8080 > 172.30.22.3.42000: Flags [P.], cksum 0x84dd (incorrect -> 0xe64b), seq 1:116, ack 89, win 502, options [nop,nop,TS val 1892113104 ecr 3200284558], length 115: HTTP, length: 115
      HTTP/1.1 200
      Content-Type: text/plain;charset=UTF-8
      Content-Length: 2
      Date: Fri, 06 Mar 2020 08:29:05 GMT
      
      OK[!http]
      
      
      • 第一條 通過47980埠向DNS服務器發起決議域名clientip.default.svc.cluster.local的請求
      • 第二條 DNS服務決議出clientip.default.svc.cluster.local對應的IP是10.254.0.30
      • 第三條通過42000埠 向10.254.0.30:8080 發出請求
      • 請求10.254.0.30:8080在input鏈上被IPVS匹配,因為10.254.0.30是service的ClusterIp,IPVS匹配成功,采用NAT機制將目的地址轉換成172.30.22.4.8080,進入postrouting,master節點上的路由資訊發現發往172.30.22.4的請求還是通過docker0網路設備發送,所以在docker0上又收到了第四條記錄,即向真實服務172.30.22.4.8080發起的請求
      • 第五條記錄 真實的web服務172.30.22.4在完成處理后直接將結果回傳到了172.30.22.3中,沒有經過IPVS的mssq
    3. 觀察flannel.1設備的輸出,此時是不會出現和請求172.30.22.4相關的資訊,此處略去

例子2

curl服務對應的pod在master節點上,web服務對應的pod在slave節點上,由拓撲圖可知,這時要完成從curl的pod內部訪問到web服務依次要經過 master.docker0->master.flannel.1->master.wlp3s0->slave.wlo1->slave.flannel.1->slave.docker0

  1. 修改web的啟動檔案,將nodeSelector的值修改成sample=slave,重新啟動web應用

    $ kubectl get pod -o wide
    NAME                                   READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
    clientip-deployment-68c57b7965-pmwp2   1/1     Running   0          33s   172.30.78.3   slave    <none>           <none>
    curl                                   1/1     Running   0          48m   172.30.22.3   master   <none>           <none>
    
    $ kubectl get svc
    NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    clientip     ClusterIP   10.254.167.63   <none>        8080/TCP   94s
    kubernetes   ClusterIP   10.254.0.1      <none>        443/TCP    25d
    
    
  2. 日志監控

    1. 監控web服務的日志

      $ kubectl logs -f clientip-deployment-68c57b7965-pmwp2
      
      
    2. 監控master各個網路設備的日志

      $ tcpdump -n -vv -i docker0
      $ tcpdump -n -vv -i flannel.1
      $ tcpdump -n -vv -i wlp3s0
      
      
    3. 監控slave節點各個網路設備日志

      
      $ tcpdump -n -vv -i docker0
      $ tcpdump -n -vv -i flannel.1
      $ tcpdump -n -vv -i wlo1
      
      
      
  3. 監控日志分析

    1. web日志

      2020-03-07 11:13:22.384  INFO 6 --- [nio-8080-exec-3] c.falcon.clientip.ClientIpController     : host isclientip:8080
      2020-03-07 11:13:22.384  INFO 6 --- [nio-8080-exec-3] c.falcon.clientip.ClientIpController     : remoteAddr is 172.30.22.3
      2020-03-07 11:13:22.384  INFO 6 --- [nio-8080-exec-3] c.falcon.clientip.ClientIpController     : remotePort is 51596
      
      
      • 對應的遠端IP是172.30.22.3,就是我們發起請求的curl pod對應的IP
    2. master網路設備的日志分析(只展示主要流程,tcp握手程序略去)

      1. docker0設備

        ...
        11:13:22.346481 IP (tos 0x0, ttl 64, id 28047, offset 0, flags [DF], proto UDP (17), length 80)
        	172.30.22.3.35482 > 10.254.0.2.53: [bad udp cksum 0xcd6e -> 0x55df!] 3111+ A? clientip.default.svc.cluster.local. (52)
        ...
        11:13:22.355447 IP (tos 0x0, ttl 62, id 34179, offset 0, flags [DF], proto UDP (17), length 130)
            10.254.0.2.53 > 172.30.22.3.35482: [udp sum ok] 3111*- q: A? clientip.default.svc.cluster.local. 1/0/0 clientip.default.svc.cluster.local. A 10.254.167.63 (102)
        ...
        11:13:22.359009 IP (tos 0x0, ttl 64, id 23895, offset 0, flags [DF], proto TCP (6), length 140)
            172.30.22.3.51596 > 10.254.167.63.8080: Flags [P.], cksum 0x74dd (incorrect -> 0x0f66), seq 1:89, ack 1, win 507, options [nop,nop,TS val 56684247 ecr 2651496809], length 88: HTTP, length: 88
                GET /header/list HTTP/1.1
                Host: clientip:8080
                User-Agent: curl/7.67.0
                Accept: */*
        ...
        11:13:22.372907 IP (tos 0x0, ttl 62, id 63303, offset 0, flags [DF], proto TCP (6), length 167)
            10.254.167.63.8080 > 172.30.22.3.51596: Flags [P.], cksum 0x077c (correct), seq 1:116, ack 89, win 502, options [nop,nop,TS val 2651496823 ecr 56684247], length 115: HTTP, length: 115
                HTTP/1.1 200
                Content-Type: text/plain;charset=UTF-8
                Content-Length: 2
                Date: Sat, 07 Mar 2020 03:13:22 GMT
        
                OK[!http]
        
        
        • 第一條 向DNS服務器發起決議域名clientip.default.svc.cluster.local的請求
        • 第二條 DNS服務決議出clientip.default.svc.cluster.local對應的IP是10.254.167.63
        • 第三條 向10.254.167.63:8080 發出請求
        • 第四條記錄 從10.254.167.63:8080回傳的資訊傳遞給了172.30.22.3.51596

        回傳資訊是從10.254.167.63:8080發回來的,和發出去的路徑是一致的,在回傳時IPVS的masq(SNAT),將真實服務器地址轉換成了虛擬地址

      2. flannel.1網路設備

        11:13:22.359020 IP (tos 0x0, ttl 63, id 23895, offset 0, flags [DF], proto TCP (6), length 140)
            172.30.22.3.51596 > 172.30.78.3.8080: Flags [P.], cksum 0xbcc1 (incorrect -> 0xc781), seq 1:89, ack 1, win 507, options [nop,nop,TS val 56684247 ecr 2651496809], length 88: HTTP, length: 88
                GET /header/list HTTP/1.1
                Host: clientip:8080
                User-Agent: curl/7.67.0
                Accept: */*
        ...
        11:13:22.372887 IP (tos 0x0, ttl 63, id 63303, offset 0, flags [DF], proto TCP (6), length 167)
            172.30.78.3.8080 > 172.30.22.3.51596: Flags [P.], cksum 0xbf97 (correct), seq 1:116, ack 89, win 502, options [nop,nop,TS val 2651496823 ecr 56684247], length 115: HTTP, length: 115
                HTTP/1.1 200
                Content-Type: text/plain;charset=UTF-8
                Content-Length: 2
                Date: Sat, 07 Mar 2020 03:13:22 GMT
        
                OK[!http]        
        
        
        • 第一條172.30.22.3發出的請求,通過51596埠,向真實的服務器172.30.78.3.8080發起請求,
        • 第二條,真實的服務器回傳回應資訊給172.30.22.3.51596
      3. wlp3s0網卡(物理網卡)

        ...
        11:13:22.359026 IP (tos 0x0, ttl 64, id 22491, offset 0, flags [none], proto UDP (17), length 190)
            192.168.0.107.33404 > 192.168.0.114.8472: [udp sum ok] OTV, flags [I] (0x08), overlay 0, instance 1
        IP (tos 0x0, ttl 63, id 23895, offset 0, flags [DF], proto TCP (6), length 140)
            172.30.22.3.51596 > 172.30.78.3.8080: Flags [P.], cksum 0xc781 (correct), seq 1:89, ack 1, win 507, options [nop,nop,TS val 56684247 ecr 2651496809], length 88: HTTP, length: 88
                GET /header/list HTTP/1.1
                Host: clientip:8080
                User-Agent: curl/7.67.0
                Accept: */* 
        ...
        11:13:22.372815 IP (tos 0x0, ttl 64, id 57065, offset 0, flags [none], proto UDP (17), length 217)
            192.168.0.114.43021 > 192.168.0.107.8472: [udp sum ok] OTV, flags [I] (0x08), overlay 0, instance 1
        IP (tos 0x0, ttl 63, id 63303, offset 0, flags [DF], proto TCP (6), length 167)
            172.30.78.3.8080 > 172.30.22.3.51596: Flags [P.], cksum 0xbf97 (correct), seq 1:116, ack 89, win 502, options [nop,nop,TS val 2651496823 ecr 56684247], length 115: HTTP, length: 115
                HTTP/1.1 200
                Content-Type: text/plain;charset=UTF-8
                Content-Length: 2
                Date: Sat, 07 Mar 2020 03:13:22 GMT
        
                OK[!http]
        
        
        • 第一條 172.30.22.3.51596向172.30.78.3.8080發出的請求,封裝到了udp資料包的內部,通過物理網卡通道192.168.0.107.33404 > 192.168.0.114.8472進行傳輸
        • 第二條 從172.30.78.3.8080向172.30.22.3.51596的回傳資訊,封裝到了udp資料包的內部,通過物理網卡通道192.168.0.114.43021 > 192.168.0.107.8472進行傳輸
    3. master節點上資料傳輸總結(通過抓包中的時間分析出資料到達各個設備的先后順序,紅色方塊curl開始)

      1. 發送流程
        1. 發起請求的pod向DNS服務器發出請求,查找clientip對應的IP地址
        2. 找到IP后向對應的地址發送真實的請求
        3. 因為這個IP地址是一個service的ClusterIP,會系結到kubernetes為每一臺節點機器創建的dummy設備kube-ipvs0上,所以宿主機會認為這是一個本機IP,進入內核的input鏈
        4. IPVS在input鏈上對這個ClusterIP進行判斷,發現是一個集群服務,會執行DNAT,找到一個真實的后端服務(172.30.78.3.8080),將請求目的地址轉換成這個真實服務,之后將請求跳轉到內核的POSTROUTING鏈上
        5. 在路由選擇階段,根據master節點的路由規則,發現發往172.30.78.0/24的請求要經過flannel.1網路設備,所以flannel.1網路設備中有了172.30.22.3.51596 > 172.30.78.3.8080的請求資訊
        6. flannel1.1網路設備,通過flanneld,查找到172.30.78.3.8080所在的物理節點,將資料包重新包裝成,追加outerIp、port資訊(192.168.0.114.8472)
        7. 此時再根據路由規則,發往192.168.0.114的請求需經過wlp3s0網卡,所以wlp3s0上收到了192.168.0.107.33404 > 192.168.0.114.8472的請求包,請求正式發送出去
      2. 接收流程
        1. wlp3s0網卡上接收到192.168.0.114.43021回傳的資訊
        2. 因為是一個vxlan格式的資料包,所以會丟個flanneld處理,將outerIp、Port資訊去除,得到內部的tcp請求資訊172.30.78.3.8080 > 172.30.22.3.51596
        3. 之后flanneld發請求資訊轉發送給flannel1.1網路設備,所以flannel1.1網路設備上我們能監聽到172.30.78.3.8080 > 172.30.22.3.51596的資料包,當資料到達INPUT時,IPVS開始作業,此時IPVS判斷出此報文是之前發出請求的回應,繼而進行SNAT(在IPVS原始碼塊的handle_response,對于tcp協議是tcp_snat_handler函式中處理),將回傳請求的源地址轉換成真實服務對應的虛擬服務地址,即10.254.167.63.8080,之后使用函式ip_vs_route_me_harder進行重新路由,
        4. 根據路由規則,發往172.30.22.3.51596的資料包,要經過docker0網路設備,所以我們在docker0設備上看到了10.254.167.63.8080 > 172.30.22.3.51596的資料包
  4. slave節點上網路設備的日志分析(只展示主要流程,tcp握手程序略去)

    1. docker0設備

      ...
      11:13:22.379401 IP (tos 0x0, ttl 62, id 23895, offset 0, flags [DF], proto TCP (6), length 140)
          172.30.22.3.51596 > 172.30.78.3.8080: Flags [P.], cksum 0xc781 (correct), seq 1:89, ack 1, win 507, options [nop,nop,TS val 56684247 ecr 2651496809], length 88: HTTP, length: 88
              GET /header/list HTTP/1.1
      ...
      11:13:22.389173 IP (tos 0x0, ttl 64, id 63303, offset 0, flags [DF], proto TCP (6), length 167)
          172.30.78.3.8080 > 172.30.22.3.51596: Flags [P.], cksum 0xbcdc (incorrect -> 0xbf97), seq 1:116, ack 89, win 502, options [nop,nop,TS val 2651496823 ecr 56684247], length 115: HTTP, length: 115
              HTTP/1.1 200
      
      
      
      • 第一條172.30.22.3發出的請求,通過51596埠,向真實的服務器172.30.78.3.8080發起請求,
      • 第二條,真實的服務器回傳回應資訊給172.30.22.3.51596
    2. flannel.1設備

      11:13:22.379392 IP (tos 0x0, ttl 63, id 23895, offset 0, flags [DF], proto TCP (6), length 140)
          172.30.22.3.51596 > 172.30.78.3.8080: Flags [P.], cksum 0xc781 (correct), seq 1:89, ack 1, win 507, options [nop,nop,TS val 56684247 ecr 2651496809], length 88: HTTP, length: 88
              GET /header/list HTTP/1.1
              Host: clientip:8080
              User-Agent: curl/7.67.0
              Accept: */*
       ...
       
      11:13:22.389192 IP (tos 0x0, ttl 63, id 63303, offset 0, flags [DF], proto TCP (6), length 167)
          172.30.78.3.8080 > 172.30.22.3.51596: Flags [P.], cksum 0xbcdc (incorrect -> 0xbf97), seq 1:116, ack 89, win 502, options [nop,nop,TS val 2651496823 ecr 56684247], length 115: HTTP, length: 115
              HTTP/1.1 200
              Content-Type: text/plain;charset=UTF-8
              Content-Length: 2
              Date: Sat, 07 Mar 2020 03:13:22 GMT
      
              OK[!http]
      
      • 第一條172.30.22.3發出的請求,通過51596埠,向真實的服務器172.30.78.3.8080發起請求,
      • 第二條,真實的服務器回傳回應資訊給172.30.22.3.51596
    3. wlo1網卡

      11:13:22.379300 IP (tos 0x0, ttl 64, id 22491, offset 0, flags [none], proto UDP (17), length 190)
          192.168.0.107.33404 > 192.168.0.114.8472: [udp sum ok] OTV, flags [I] (0x08), overlay 0, instance 1
      IP (tos 0x0, ttl 63, id 23895, offset 0, flags [DF], proto TCP (6), length 140)
          172.30.22.3.51596 > 172.30.78.3.8080: Flags [P.], cksum 0xc781 (correct), seq 1:89, ack 1, win 507, options [nop,nop,TS val 56684247 ecr 2651496809], length 88: HTTP, length: 88
              GET /header/list HTTP/1.1
              Host: clientip:8080
              User-Agent: curl/7.67.0
              Accept: */*
              
      ...
      11:13:22.389223 IP (tos 0x0, ttl 64, id 57065, offset 0, flags [none], proto UDP (17), length 217)
          192.168.0.114.43021 > 192.168.0.107.8472: [udp sum ok] OTV, flags [I] (0x08), overlay 0, instance 1
      IP (tos 0x0, ttl 63, id 63303, offset 0, flags [DF], proto TCP (6), length 167)
          172.30.78.3.8080 > 172.30.22.3.51596: Flags [P.], cksum 0xbf97 (correct), seq 1:116, ack 89, win 502, options [nop,nop,TS val 2651496823 ecr 56684247], length 115: HTTP, length: 115
              HTTP/1.1 200
              Content-Type: text/plain;charset=UTF-8
              Content-Length: 2
              Date: Sat, 07 Mar 2020 03:13:22 GMT
      
              OK[!http] 
      ...
      
      
      • 第一條 172.30.22.3.51596向172.30.78.3.8080發出的請求,封裝到了udp資料包的內部,通過物理網卡通道192.168.0.107.33404 > 192.168.0.114.8472進行傳輸
      • 第二條 從172.30.78.3.8080向172.30.22.3.51596的回傳資訊,封裝到了udp資料包的內部,通過物理網卡通道192.168.0.114.43021 > 192.168.0.107.8472進行傳輸
    4. slave節點上回應請求程序(通過抓包中的時間分析出資料到達各個設備的先后順序,紅色方塊請求進入為起始點)

      1. wlo1網卡上接收到192.168.0.107.33404的請求資訊
      2. 因為是一個vxlan格式的資料包,所以會丟個flanneld處理,將outerIp、Port資訊去除,得到內部的tcp請求資訊172.30.22.3.51596 > 172.30.78.3.8080
      3. 之后flanneld發請求資訊轉發送給flannel1.1網路設備,所以flannel1.1網路設備上我們能監聽到172.30.22.3.51596 > 172.30.78.3.8080的資料包,
      4. flannel1.1進行路由選擇,根據路由規則,發送給172.30.78.3.8080的資料包要從docker0設備進入,將請求資料包轉發到docker0設備,所以在docker0設備上監聽到了172.30.22.3.51596 > 172.30.78.3.8080的請求資料包
      5. 172.30.78.3對應的pod回應請求,并構造response回傳172.30.22.3.51596,在docker0設備上有了172.30.78.3.8080 > 172.30.22.3.51596的回應資訊
      6. 根據slave上的路由規則,發往172.30.22.3.51596的資料包,要經過flannel1.1網路設備,所以flannel.1網路設備中有了172.30.78.3.8080 > 172.30.22.3.51596的回應資訊
      7. flannel1.1網路設備,將資料發送給flanneld,flanneld查找到172.30.22.3.51596所在的物理節點,將資料包重新包裝成,追加outerIp、port資訊(192.168.0.107.8472),之后通過路由規則,發往192.168.0.107.8472的資料包從wlo1走,所以在wlo1網卡上出現192.168.0.114.43021 > 192.168.0.107.8472的資料包

例子3

只在slave上啟動一個web服務,type設定成NodePort,對應的nodePort設定成8086,從master宿主機上使用curl http://slaveIp:8088/header/list 訪問web服務(直接從slave上訪問,資料不需要傳輸,無法看到slave機器上物理網卡上的資料包,所以為了分析,我們從master上訪問)

原理

當創建NodePort型別的service時,Kubernetes會從API Server指定的引數--service-node-port-range中選擇一個port分配給service,也可以自己通過.spec.ports[*].nodePort自己指定,之后kubernetes會在集群的每個node上監聽對應的port,

除了在所有節點節點上監聽port外,kubernetes會自動給我們創建一個ClusterIP型別的service,所以創建NodePort的service后,也可以像上個例子一樣在集群內部通過 service Name+ service Port的形式訪問

此時資料包不需要在集群內pod中跨主機流轉,所以資料包不會經過flannel.1,資料包處理流程: master.wlp3s0->.slave.wlo1->slave.docker0->slave.docker0->slave.wlo1-> master.wlp3s0

啟動服務
  1. 修改web啟動檔案

    $cat > web.yml <<EOF
    apiVersion: v1
    kind: Service
    metadata:
      name: clientip
    spec:
      type: NodePort
      selector:
        app: clientip
      ports:
      - name: http
        port: 8080
        targetPort: 8080
        nodePort: 8086
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: clientip-deployment
    spec:
      selector:
        matchLabels:
          app: clientip
      replicas: 1
      template:
        metadata:
          labels:
            app: clientip
        spec:
          nodeSelector:
            sample: slave
          containers:
          - name: clientip
            image: 192.168.0.107/k8s/client-ip-test:0.0.2
            ports:
            - containerPort: 8080
    EOF
    
    
  2. 啟動服務

    $ kubectl create -f web.yml
    service/clientip created
    deployment.apps/clientip-deployment created
    
    $ kubectl get pod -o wide
    NAME                                   READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
    clientip-deployment-68c57b7965-28w4t   1/1     Running   0          10s   172.30.78.3   slave   <none>           <none>
    $ kubectl get svc -o wide
    NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGE   SELECTOR
    clientip     NodePort    10.254.85.24   <none>        8080:8086/TCP   17s   app=clientip
    kubernetes   ClusterIP   10.254.0.1     <none>        443/TCP         27d   <none>
    
    
日志監控
  1. 監控web服務的日志

    $ kubectl logs -f clientip-deployment-68c57b7965-28w4t
    
    
  2. 監控master wlp3s0網卡的日志

    $ tcpdump -n -vv -i wlp3s0
    
    
  3. 監控slave節點各個網路設備日志

    
    $ tcpdump -n -vv -i docker0
    $ tcpdump -n -vv -i flannel.1
    $ tcpdump -n -vv -i wlo1
    
    
    
日志分析(只展示主要流程,tcp握手程序略去)
  1. web日志

    2020-03-08 10:15:01.498  INFO 6 --- [nio-8080-exec-2] c.falcon.clientip.ClientIpController     : host is192.168.0.114:8086
    2020-03-08 10:15:01.499  INFO 6 --- [nio-8080-exec-2] c.falcon.clientip.ClientIpController     : remoteAddr is 172.30.78.1
    2020-03-08 10:15:01.499  INFO 6 --- [nio-8080-exec-2] c.falcon.clientip.ClientIpController     : remotePort is 38362
    
    
    • 主意remoteAddr對應的值是172.30.78.1,并不是我們的宿主機IP,原因參考請求程序
  2. slave 日志

    1. docker0設備日志

      ...
      10:15:01.494019 IP (tos 0x0, ttl 63, id 41431, offset 0, flags [DF], proto TCP (6), length 145)
          172.30.78.1.38362 > 172.30.78.3.8080: Flags [P.], cksum 0x171b (correct), seq 0:93, ack 1, win 502, options [nop,nop,TS val 670876057 ecr 1109116899], length 93: HTTP, length: 93
              GET /header/list HTTP/1.1
              Host: 192.168.0.114:8086
              User-Agent: curl/7.58.0
              Accept: */*
      
      ...
      
      10:15:01.503806 IP (tos 0x0, ttl 64, id 34492, offset 0, flags [DF], proto TCP (6), length 167)
          172.30.78.3.8080 > 192.168.0.107.38362: Flags [P.], cksum 0xbbce (incorrect -> 0x0f9e), seq 1:116, ack 94, win 502, options [nop,nop,TS val 1109116911 ecr 670876057], length 115: HTTP, length: 115
              HTTP/1.1 200
              Content-Type: text/plain;charset=UTF-8
              Content-Length: 2
              Date: Sun, 08 Mar 2020 02:15:01 GMT
      
              OK[!http]
      ...
      
      
      • 第一條,請求從docker0進入172.30.78.3.8080,注意此時的請求是從172.30.78.1.38362過來的,就是我們在web容器中看到的remoteAddr,原因參考請求程序

      • 第二條,請求處理后從docker0回傳,這時對應的回應回傳的地址又變成了實際發出訪問的地址192.168.0.107.38362

    2. flnanel.1設備日志

      tcpdump -n -vv -i flannel.1
      tcpdump: listening on flannel.1, link-type EN10MB (Ethernet), capture size 262144 bytes
      
                                 
      
      • 說明沒有相關資料包經過
    3. wlo1物理網卡日志

      ...
      10:15:01.493998 IP (tos 0x0, ttl 64, id 41431, offset 0, flags [DF], proto TCP (6), length 145)
          192.168.0.107.38362 > 192.168.0.114.8086: Flags [P.], cksum 0x8928 (correct), seq 1:94, ack 1, win 502, options [nop,nop,TS val 670876057 ecr 1109116899], length 93
      
      ...
      10:15:01.503827 IP (tos 0x0, ttl 63, id 34492, offset 0, flags [DF], proto TCP (6), length 167)
          192.168.0.114.8086 > 192.168.0.107.38362: Flags [P.], cksum 0x489f (correct), seq 1:116, ack 94, win 502, options [nop,nop,TS val 1109116911 ecr 670876057], length 115
      ...
      
      
      • 第一條,slave主機收到192.168.0.107.38362發過來的請求
      • 第二條,slave將web容器回應的內容回傳給192.168.0.107.38362
  3. master wlp3s0網卡日志

    ...
    10:15:01.447172 IP (tos 0x0, ttl 64, id 41431, offset 0, flags [DF], proto TCP (6), length 145)
        192.168.0.107.38362 > 192.168.0.114.8086: Flags [P.], cksum 0x82b1 (incorrect -> 0x8928), seq 1:94, ack 1, win 502, options [nop,nop,TS val 670876057 ecr 1109116899], length 93
    ...
    10:15:01.460324 IP (tos 0x0, ttl 63, id 34492, offset 0, flags [DF], proto TCP (6), length 167)
        192.168.0.114.8086 > 192.168.0.107.38362: Flags [P.], cksum 0x489f (correct), seq 1:116, ack 94, win 502, options [nop,nop,TS val 1109116911 ecr 670876057], length 115
    ...
    
    
    • 第一條向192.168.0.114.8086發送請求
    • 第二條從192.168.0.114.8086接收到回應
  4. slave上回應請求程序總結(紅色方塊請求進入為起始點)

    從master到slave的請求程序和普通請求一樣,此處不在描述

    1. wlo1物理網卡收到請求,發現是訪問自己機器的IP,進入Netfilter的INPUT鏈

    2. IPVS在input鏈上判斷訪問的地址192.168.0.114.8086是一個集群服務(為什么能判斷出來,參考ipvs判斷原理),從自己的hash表中選擇一個真實的服務172.30.78.3.8080,并做DNAT,將請求的目的地址換成這個真實的服務器地址,進入POSTROUTING階段

    3. 在POSTROUTING階段,按照IPTABLES的規則會進行masquerade(為什么執行,參考執行masquerade的原因),之后進行路由選擇,根據slave的路由規則表,發往172.30.78.3.8080的資料需要經過docker0,根據masquerade的原理,在發送時將源地址變成了docker0網路設備的地址

      $ ip addr
      6: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
          link/ether 02:42:0d:ab:b0:60 brd ff:ff:ff:ff:ff:ff
          inet 172.30.78.1/24 brd 172.30.78.255 scope global docker0
             valid_lft forever preferred_lft forever
          inet6 fe80::42:dff:feab:b060/64 scope link
             valid_lft forever preferred_lft forever
      
      

      對應的地址是172.30.78.1,這就是為什么我們在web日志,以及在docker0網路上看到請求是172.30.78.1的原因

    4. 之后請求轉發到docker0網路,從docker0網路進入到web容器內

    5. web容器處理完請求構成回應體,在回傳時發現這個請求是經過masquerade進來的,回傳時查找masquerade前的真實請求發起者,將資料回傳地址設定為192.168.0.107.38362,之后根據路由規則,發送給192.168.0.107.38362的資料包,需要從物理網卡wlo1發送,所以資料轉發給了wlo1網卡,在進入之前,會執行IPVS的masquerade,將源地址修改成192.168.0.114,并通過wlo1網卡發送給master

Slave上資料流轉原理
  1. IPVS判斷出192.168.0.114.8086是集群服務原理

    我們知道IPVS根據自己的hash表中的內容進行判斷,所以kubernetes只需要把集群服務相關的資訊存入到IPVS的hash表中就能實作了,利用ipvsadm工具查看當啟動一個NodePort的service后,kubernetes會在這個hash表中存入哪些內容(下面命令輸出中略去了不相干的記錄)

    $ ipvsadm --list
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  localhost:8086 rr
      -> 172.30.78.3:http-alt         Masq    1      0          0
    TCP  slave:8086 rr
      -> 172.30.78.3:http-alt         Masq    1      0          0
    TCP  promote.cache-dns.local:http rr
      -> 172.30.78.3:http-alt         Masq    1      0          0
    ...	
    
    
    • 可以看到kubernetes不僅將自動創建的ClusterIP對應的記錄插入到hash表中,針對NodePort服務,還會多插入兩條記錄localhost和hostname對應的規則,這樣當我們訪問192.168.0.114.8086時,能匹配到slave:8086,所以IPVS判斷出這訪問的是一個集群服務,會進行DNAT
  2. 請求在POSTROUTING階段執行masquerade的原理

    1. 首先看下采用IPVS模式時,kubernetes給我們創建的ipset,及其作用

      name members usage
      -CLUSTER-IP All service IP + port Mark-Masq for cases that masquerade-all=true or clusterCIDR specified
      -LOOP-BACK All service IP + port + IP masquerade for solving hairpin purpose
      -EXTERNAL-IP service external IP + port masquerade for packages to external IPs
      -LOAD-BALANCER load balancer ingress IP + port masquerade for packages to load balancer type service
      -LOAD-BALANCER-LOCAL LB ingress IP + port with externalTrafficPolicy=local accept packages to load balancer with externalTrafficPolicy=local
      -LOAD-BALANCER-FW load balancer ingress IP + port with loadBalancerSourceRanges package filter for load balancer with loadBalancerSourceRanges specified
      -LOAD-BALANCER-SOURCE-CIDR load balancer ingress IP + port + source CIDR package filter for load balancer with loadBalancerSourceRanges specified
      -NODE-PORT-TCP nodeport type service TCP port masquerade for packets to nodePort(TCP)
      -NODE-PORT-LOCAL-TCP nodeport type service TCP port with externalTrafficPolicy=local accept packages to nodeport service with externalTrafficPolicy=local
      -NODE-PORT-UDP nodeport type service UDP port masquerade for packets to nodePort(UDP)
      -NODE-PORT-LOCAL-UDP nodeport type service UDP port with externalTrafficPolicy=local accept packages to nodeport service with externalTrafficPolicy=local
      • 其中KUBE-NODE-PORT-TCP 里面存盤的是需要進行masquerade的本機埠號
    2. 其次,需要知道kubernetes是如何利用這些ipset的,再看下kubernetes為我們在iptables中追加的規則

    下面的輸出內容是在kube-proxy啟動引數:iptables.masqueradeAll=false;clusterCIDR=172.30.0.0/16時的結果,配置成其他的KUBE-SERVICES的規則鏈會稍有不同,輸出進行了精簡只包含了和kubernetes相關的規則

     ```
     $ iptables -n -L -t nat
     
     Chain PREROUTING (policy ACCEPT)
     target     prot opt source               destination
     KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
     
     Chain OUTPUT (policy ACCEPT)
     target     prot opt source               destination
     KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
     
     Chain POSTROUTING (policy ACCEPT)
     target     prot opt source               destination
     KUBE-POSTROUTING  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */
     
     Chain KUBE-FIREWALL (0 references)
     target     prot opt source               destination
     KUBE-MARK-DROP  all  --  0.0.0.0/0            0.0.0.0/0
     
     Chain KUBE-KUBELET-CANARY (0 references)
     target     prot opt source               destination
     
     Chain KUBE-LOAD-BALANCER (0 references)
     target     prot opt source               destination
     KUBE-MARK-MASQ  all  --  0.0.0.0/0            0.0.0.0/0
     
     Chain KUBE-MARK-DROP (1 references)
     target     prot opt source               destination  
     
     Chain KUBE-MARK-MASQ (2 references)
     target     prot opt source               destination
     MARK       all  --  0.0.0.0/0            0.0.0.0/0            MARK or 0x4000
     
     Chain KUBE-NODE-PORT (1 references)
     target     prot opt source               destination
     KUBE-MARK-MASQ  tcp  --  0.0.0.0/0            0.0.0.0/0            /* Kubernetes nodeport TCP port for masquerade purpose */ match-set KUBE-NODE-PORT-TCP dst
     
     Chain KUBE-POSTROUTING (1 references)
     target     prot opt source               destination
     MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000
     MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOOP-BACK dst,dst,src
     
     Chain KUBE-SERVICES (2 references)
     target     prot opt source               destination
     KUBE-MARK-MASQ  all  -- !172.30.0.0/16        0.0.0.0/0            /* Kubernetes service cluster ip + port for masquerade purpose */ match-set KUBE-CLUSTER-IP dst,dst
     KUBE-NODE-PORT  all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
     ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-CLUSTER-IP dst,dst
    
     ```
     
     1. PREROUTING階段
     
     	* 在PREROUTING階段,所有請求會jump到KUBE-SERVICES規則鏈
     	* 在KUBE-SERVICES規則鏈里,根據我們訪問的地址salveIp:8086,第一條不滿足,會匹配到第二條即訪問的地址是本機,所以jump到KUBE-NODE-PORT規則鏈
     	* 在KUBE-NODE-PORT規則鏈中會判斷請求目的埠號是否在KUBE-NODE-PORT-TCP這個ipset中,是的話跳轉到KUBE-MARK-MASQ,看下我們啟動NodePort service后這個ipset中的值
     		
     		```
     		$ ipset  --list KUBE-NODE-PORT-TCP
     		Name: KUBE-NODE-PORT-TCP
     		Type: bitmap:port
     		Revision: 3
     		Header: range 0-65535
     		Size in memory: 8268
     		References: 1
     		Number of entries: 1
     		Members:
     		8086
     		
     		```
     		kubernetes的確把我們創建的服務對應的node port值存入這個里面了
     	* KUBE-MARK-MASQ規則鏈對進入這個規則鏈的所有請求都打上一個標簽0x4000
     	
     1. POSTROUTING階段
     	* 在POSTROUTING階段,所有的請求都jump到KUBE-POSTROUTING規則鏈中
     	* 在KUBE-POSTROUTING規則鏈中,根據第一條規則,當進來的資料包有0x4000標記時進行MASQUERADE,根據在PREROUTING階段中的處理,訪問salveIp:8086的請求會滿足條規則,所以會對我們的請求進行MASQUERADE
    

總結

這樣,本文用三個例子,通過用tcpdump對各個網路設備上資料包的分析,闡述了不同情況下kubernetes的網路請求程序,最后一個例子結合kubernetes給我創建的ipset、iptables規則講述了kubernetes實作服務訪問的原理,前面兩個例子讀者也可以采用這樣的方式結合下iptables中的規則鏈,來驗證下資料的流轉流程,

另外最后一個例子,還可以通過集群中master節點的8086來訪問web服務,這時資料包還會經過兩個節點的flannel.1網路設備,但不會經過master.docker0設備,并且web中收到請求的remoteAddr也會不一樣,下面只給出請求程序不再給出具體的tcpdump日志資訊

請求:
master.wlp3s0->master.flannel.1->master.wlp3s0->slave.wlo1->slave.flannel.1->slave.docker0

回應:
slave.docker0->slave.flannel.1->slave.wlo1->master.wlp3s0->master.flannel.1-> master.wlp3s0

讀者朋友可以自行試下,結合tcpdump工具和iptables中的規則對資料包流轉程序進行分析,

題外話

額外的一點思考,為啥kubernetes要設計的這么復雜對通過node port的請求進行masquerade呢,這是因為當創建一個NodePort服務后,kubernetes不只是讓服務對應的endpoint所在的節點上能夠提供服務,而是讓集群中所有的節點都可以在對應的port上提供服務,這樣我們從外部通過node port訪問集群服務時,有可能訪問的服務對應的pod不在我們訪問的節點上,這樣要是不經過masquerade,真實的endpoint處理完請求后在回應時看到的也是真實的clientIP,資料就不會先回傳到client一開始請求的node上,而是直接回傳給了client,這樣client收到結果發現是和請求的地址不一樣的服務器給了回應,會認為這是不合法的的回應體,所以為了讓client能從請求的節點上拿到回應體,所以需要對外部訪問node port的請求統一做masquerade,這樣資料回傳時,會首先回傳到client請求的節點上,再由此節點回傳給client,如果因為業務需求,如一些審計什么的,必須要獲取到client的真實IP,可以考慮下面三種方式:

  1. 在集群外層再加一個代理(ingress方式),在代理里面獲取client IP,存入約定好的header 頭中,在集群內的服務通過這個header資訊來獲取
  2. POD直接設定成hostNetwork
  3. 通過將服務設定{"externalTrafficPolicy":"Local"}},這時如果pod不在對應的節點上時,是無法提供服務的

kubernetes的官網對此的探討:
Using Source IP

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/38927.html

標籤:其他

上一篇:Kubernetes(十八) kube-proxy 詳解

下一篇:http協議

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more