Kubernetes K8S 基本概述、設計架構和設計理念

来源:https://www.cnblogs.com/zhanglianghhh/archive/2020/07/28/13388669.html
-Advertisement-
Play Games

Kubernetes K8S 概述、特性與架構說明,以及核心技術概念和API對象詳解 ...


 

Kubernetes K8S 概述、特性與架構說明,以及核心技術概念和API對象詳解

 

Kubernetes概述

Kubernetes是一個開源的,用於管理雲平臺中多個主機上的容器化的應用,Kubernetes的目標是讓部署容器化的應用簡單並且高效(powerful),Kubernetes提供了應用部署、規劃、更新、維護的一種機制。

在所有的容器編排工具中(類似的還有 docker swarm / mesos等),Kubernetes的生態系統更大、增長更快,有更多的支持、服務和工具可供用戶選擇。

Kubernetes是Google開源的容器集群管理系統。最初源於谷歌內部的Borg,是Google基於Borg開源的容器編排調度引擎。它構建在Docker技術之上,為跨主機的容器化應用提供資源調度、服務發現、高可用管理和彈性伸縮等一整套功能,它提供完善的管理工具,涵蓋開發、部署測試、運維監控等各個環節。

它的目標不僅僅是一個編排系統,而是提供一個規範,可以讓你來描述集群的架構,定義服務的最終狀態,Kubernetes可以幫你將系統自動的達到和維持在這個狀態。

重點:跨機器、跨平臺;協調資源使用

容器化越來越流行,主要原因是它帶來的諸多好處:

  • 敏捷地創建和部署應用程式:相較於創建虛擬機鏡像,創建容器鏡像更加容易和快速
  • 持續構建集成:可以更快更頻繁地構建容器鏡像、部署容器化的應用程式、並且輕鬆地回滾應用程式
  • 分離開發和運維的關註點:在開發構建階段就完成容器鏡像的構建,構建好的鏡像可以部署到多種基礎設施上。這種做法將開發階段需要關註的內容包含在如何構建容器鏡像的過程中,將部署階段需要關註的內容聚焦在如何提供基礎設施以及如何使用容器鏡像的過程中。降低了開發和運維的耦合度
  • 可監控性:不僅可以查看操作系統級別的資源監控信息,還可以查看應用程式健康狀態以及其他信號的監控信息
  • 開發、測試、生產不同階段的環境一致性:開發階段在筆記本上運行的容器與測試、生產環境中運行的容器一致
  • 跨雲服務商、跨操作系統發行版的可移植性:容器可運行在 Ubuntu、RHEL、CoreOS、CentOS等不同的操作系統發行版上,可以運行在私有化部署、Google Kubernetes Engine、AWS、阿裡雲等不同的雲供應商的環境中
  • 以應用程式為中心的管理:虛擬機時代的考慮的問題是在虛擬硬體上運行一個操作系統,而容器化時代,問題的焦點則是在操作系統的邏輯資源上運行一個應用程式
  • 松耦合、分散式、彈性、無約束的微服務應用程式被切分成更小的、獨立的微服務,並可以動態部署和管理,而不是一個部署在專屬機器上的龐大的單片應用程式
  • 資源隔離:確保應用程式性能不受干擾
  • 資源利用:資源高效、高密度利用

 

Kubernetes特性

1、自動化部署:yaml部署到K8S,會根據應用程式計算資源需求,自動分配到node。

2、系統自愈:重啟已經停機的容器;替換、kill 那些不滿足自定義健康檢查條件的容器;在容器就緒之前,避免調用者發現該容器。

3、水平擴展:HPA周期調度RC的副本數量,將用戶定義的resource值匹配。

4、服務發現和負載均衡:內置服務發現功能。可以通過 DNS 名稱或 IP 地址暴露容器的訪問方式;並且可以在同組容器內分發負載以實現負載均衡。

5、存儲編排:可以自動掛載指定的存儲系統,例如 local stroage/nfs/雲存儲等。

6、自動更新和回滾:可以在 K8S 中聲明你期望應用程式容器應該達到的狀態,Kubernetes將以合適的速率調整容器的實際狀態,並逐步達到最終期望的結果,不會同時殺掉應用。更新出錯,自動恢復到原先狀態。

 

Kubernetes架構設計

 

Master說明

Master:集群控制節點,負責整個集群的管理和控制。

API Server:提供介面,資源增刪改查入口。並提供認證、授權、訪問控制、API註冊和發現等機制。

Controller Manager:所有資源對象的自動化控制中心;負責維護集群的狀態,比如故障檢測、自動擴展、滾動更新等。

Scheduler:負責資源調度,按照預定的調度策略將Pod調度到相應的機器上。

Etcd:保存整個集群的狀態。

Node說明

Node:工作節點,聽從master的工作分配

Kubelet:Pod容器創建、啟停、集群管理等任務;同時也負責Volume(CVI)和網路(CNI)的管理。

Kube-proxy:實現service的通信與負載均衡組件。

Docker:docker引擎,負責本機容器的創建和管理工作。

其他組件說明

除了核心組件,還有一些推薦的Add-ons:

  • kube-dns:負責為整個集群提供DNS服務
  • Ingress Controller:為服務提供外網入口
  • Heapster/metrics-server:提供資源監控
  • Dashboard:提供GUI
  • Federation:提供跨可用區的集群
  • Fluentd-elasticsearch:提供集群日誌採集、存儲與查詢

示意圖

kubernetes master

 

kubernetes node

 

分層架構

Kubernetes設計理念和功能其實就是一個類似Linux的分層架構,如下圖所示:

 

  • 核心層:Kubernetes最核心的功能,對外提供API構建高層的應用,對內提供插件式應用執行環境
  • 應用層:部署(無狀態應用、有狀態應用、批處理任務、集群應用等)和路由(服務發現、DNS解析等)
  • 管理層:系統度量(如基礎設施、容器和網路的度量),自動化(如自動擴展、動態Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)
  • 介面層:kubectl命令行工具、客戶端SDK以及集群聯邦
  • 生態系統:在介面層之上的龐大容器集群管理調度的生態系統,可以劃分為兩個範疇

「Kubernetes外部:日誌、監控、配置管理、CI、CD、Workflow、FaaS、OTS應用、ChatOps等」

「Kubernetes內部:CRI、CNI、CVI、鏡像倉庫、Cloud Provider、集群自身的配置和管理等」

 

Kubernetes的核心技術概念和API對象

API對象是K8s集群中的管理操作單元。K8s集群系統每支持一項新功能,引入一項新技術,一定會新引入對應的API對象,支持對該功能的管理操作。例如副本集Replica Set對應的API對象是RS。

每個API對象都有3大類屬性:元數據metadata、規範spec和狀態status。元數據是用來標識API對象的,每個對象都至少有3個元數據:namespace,name和uid;除此以外還有各種各樣的標簽labels用來標識和匹配不同的對象,例如用戶可以用標簽env來標識區分不同的服務部署環境,分別用env=dev、env=testing、env=production來標識開發、測試、生產的不同服務。規範描述了用戶期望K8s集群中的分散式系統達到的理想狀態(Desired State),例如用戶可以通過複製控制器Replication Controller設置期望的Pod副本數為3;status描述了系統實際當前達到的狀態(Status),例如系統當前實際的Pod副本數為2;那麼複製控制器當前的程式邏輯就是自動啟動新的Pod,爭取達到副本數為3。

K8s中所有的配置都是通過API對象的spec去設置的,也就是用戶通過配置系統的理想狀態來改變系統,這是k8s重要設計理念之一,即所有的操作都是聲明式(Declarative)的而不是命令式(Imperative)的。聲明式操作在分散式系統中的好處是穩定,不怕丟操作或運行多次,例如設置副本數為3的操作運行多次也還是一個結果,而給副本數加1的操作就不是聲明式的,運行多次結果就錯了。

 

微服實例-Pod

K8s有很多技術概念,同時對應很多API對象,最重要的也是最基礎的是微服務Pod。

Pod是在K8s集群中運行部署應用或服務的最小單元,它是可以支持多容器的。Pod的設計理念是支持多個容器在一個Pod中共用網路地址和文件系統,可以通過進程間通信和文件共用這種簡單高效的方式組合完成服務。

Pod是K8s集群中所有業務類型的基礎,可以看作運行在K8s集群中的小機器人,不同類型的業務就需要不同類型的小機器人去執行。目前K8s中的業務主要可以分為長期伺服型(long-running)、批處理型(batch)、節點後臺支撐型(node-daemon)和有狀態應用型(stateful application);分別對應的小機器人控制器為Deployment、Job、DaemonSet和StatefulSet,本文後面會一一介紹。

 

複製控制器-Replication Controller,RC

RC是K8s集群中最早的保證Pod高可用的API對象。通過監控運行中的Pod來保證集群中運行指定數目的Pod副本。指定的數目可以是多個也可以是1個;少於指定數目,RC就會啟動運行新的Pod副本;多於指定數目,RC就會殺死多餘的Pod副本

即使在指定數目為1的情況下,通過RC運行Pod也比直接運行Pod更明智,因為RC也可以發揮它高可用的能力,保證永遠有1個Pod在運行。

RC是K8s較早期的技術概念,只適用於長期伺服型的業務類型,比如控制小機器人提供高可用的Web服務。

 

副本集(設置)- Replica Set,RS

RS是新一代RC,提供同樣的高可用能力,區別主要在於RS後來居上,能支持更多種類的匹配模式。副本集對象一般不單獨使用,而是作為Deployment的理想狀態參數使用。

 

部署- Deployment

Deployment表示用戶對K8s集群的一次更新操作。Deployment是一個比RS應用模式更廣的API對象,可以是創建一個新的服務,更新一個新的服務,也可以是滾動升級一個服務

滾動升級一個服務,實際是創建一個新的RS,然後逐漸將新RS中副本數增加到理想狀態,將舊RS中的副本數減小到0的複合操作;這樣一個複合操作用一個RS是不太好描述的,所以用一個更通用的Deployment來描述。

以K8s的發展方向,未來對所有長期伺服型的的業務的管理,都會通過Deployment來管理。

 

服務-Service

RC、RS和Deployment只是保證了支撐服務的微服務Pod的數量,但是沒有解決如何訪問這些服務的問題。

一個Pod只是一個運行服務的實例,隨時可能在一個節點上停止,在另一個節點以一個新的IP啟動一個新的Pod,因此不能以固定的IP和埠號提供服務。要穩定地提供服務需要服務發現和負載均衡能力。服務發現完成的工作,是針對客戶端訪問的服務,找到對應的的後端服務實例。

K8s集群中,客戶端需要訪問的服務就是Service對象。每個Service會對應一個集群內部有效的虛擬IP,集群內部通過虛擬IP訪問一個服務。在K8s集群中微服務的負載均衡是由Kube-proxy實現的。Kube-proxy是K8s集群內部的負載均衡器。

它是一個分散式代理伺服器,在K8s的每個節點上都有一個;這一設計體現了它的伸縮性優勢,需要訪問服務的節點越多,提供負載均衡能力的Kube-proxy就越多,高可用節點也隨之增多。與之相比,我們平時在伺服器端做個反向代理做負載均衡,還要進一步解決反向代理的負載均衡和高可用問題。

 

任務-Job

Job是K8s用來控制批處理型任務的API對象。批處理業務與長期伺服業務的主要區別是批處理業務的運行有頭有尾,而長期伺服業務在用戶不停止的情況下永遠運行。

Job管理的Pod根據用戶的設置把任務成功執行完成就自動退出了。成功完成的標誌根據不同的spec.completions策略而不同:單Pod型任務有一個Pod成功就標誌完成;定數成功型任務保證有N個任務全部成功;工作隊列型任務根據應用確認的全局成功而標誌成功。

 

後臺支撐服務集-DaemonSet

長期伺服型和批處理型服務的核心在業務應用,可能有些節點運行多個同類業務的Pod,有些節點上又沒有這類Pod運行;而後臺支撐型服務的核心關註點是在K8s集群中的節點(物理機或虛擬機),要保證每個節點上都有一個此類Pod運行

節點可能是所有集群節點也可能是通過nodeSelector選定的一些特定節點。典型的後臺支撐型服務包括:存儲,日誌和監控等在每個節點上支持K8s集群運行的服務

 

有狀態服務集-StatefulSet

K8s在1.3版本里發佈了Alpha版的PetSet功能。在雲原生應用的體系裡,有下麵兩組近義詞;第一組是無狀態(stateless)、牲畜(cattle)、無名(nameless)、可丟棄(disposable);第二組是有狀態(stateful)、寵物(pet)、有名(having name)、不可丟棄(non-disposable)。

RC和RS主要是控制提供無狀態服務的,其所控制的Pod的名字是隨機設置的,一個Pod出故障了就被丟棄掉,在另一個地方重啟一個新的Pod,名字變了;名字和啟動在哪兒都不重要,重要的只是Pod總數;而StatefulSet是用來控制有狀態服務,StatefulSet中的每個Pod的名字都是事先確定的,不能更改。StatefulSet中Pod的名字的作用,是關聯與該Pod對應的狀態。

對於RC和RS中的Pod,一般不掛載存儲或者掛載共用存儲,保存的是所有Pod共用的狀態,Pod和普通物品一樣沒有什麼分別;對於StatefulSet中的Pod,每個Pod掛載自己獨立的存儲,如果一個Pod出現故障,從其他節點啟動一個同樣名字的Pod,要掛載上原來Pod的存儲繼續以它的狀態提供服務

適合於StatefulSet的業務包括資料庫服務MySQL和PostgreSQL,集群化管理服務Zookeeper、etcd等有狀態服務。StatefulSet的另一種典型應用場景是作為一種比普通容器更穩定可靠的模擬虛擬機的機制。傳統的虛擬機正是一種有狀態的物品,運維人員需要不斷地維護它,容器剛開始流行時,我們用容器來模擬虛擬機使用,所有狀態都保存在容器里,而這已被證明是非常不安全、不可靠的。使用StatefulSet,Pod仍然可以通過漂移到不同節點提供高可用,而存儲也可以通過外掛的存儲來提供高可靠性,StatefulSet做的只是將確定的Pod與確定的存儲關聯起來保證狀態的連續性

 

集群聯邦-Federation

K8s在1.3版本里發佈了beta版的Federation功能。在雲計算環境中,服務的作用距離範圍從近到遠一般可以有:同主機(Host,Node)、跨主機同可用區(Available Zone)、跨可用區同地區(Region)、跨地區同服務商(Cloud Service Provider)、跨雲平臺。K8s的設計定位是單一集群在同一個地域內,因為同一個地區的網路性能才能滿足K8s的調度和計算存儲連接要求。而聯合集群服務就是為提供跨Region跨服務商K8s集群服務而設計的。

每個K8s Federation有自己的分散式存儲、API Server和Controller Manager。用戶可以通過Federation的API Server註冊該Federation的成員K8s Cluster。當用戶通過Federation的API Server創建、更改API對象時,Federation API Server會在自己所有註冊的子K8s Cluster都創建一份對應的API對象。在提供業務請求服務時,K8s Federation會先在自己的各個子Cluster之間做負載均衡,而對於發送到某個具體K8s Cluster的業務請求,會依照這個K8s Cluster獨立提供服務時一樣的調度模式去做K8s Cluster內部的負載均衡。而Cluster之間的負載均衡是通過功能變數名稱服務的負載均衡來實現的。

所有的設計都儘量不影響K8s Cluster現有的工作機制,這樣對於每個子K8s集群來說,並不需要更外層的有一個K8s Federation,也就是意味著所有現有的K8s代碼和機制不需要因為Federation功能有任何變化。

 

存儲捲-Volume

K8s集群中的存儲捲跟Docker的存儲捲有些類似,只不過Docker的存儲捲作用範圍為一個容器,而K8s的存儲捲的生命周期和作用範圍是一個Pod。每個Pod中聲明的存儲捲由Pod中的所有容器共用

K8s支持非常多的存儲捲類型,特別是支持多種公有雲平臺的存儲,包括AWS,Google和Azure雲;支持多種分散式存儲包括GlusterFS和Ceph;也支持較容易使用的主機本地目錄hostPath和NFS。

K8s還支持使用Persistent Volume Claim即PVC這種邏輯存儲,使用這種存儲,使得存儲的使用者可以忽略後臺的實際存儲技術(例如AWS,Google或GlusterFS和Ceph),而將有關存儲實際技術的配置交給存儲管理員通過Persistent Volume來配置

 

持久存儲捲-Persistent Volume,PV和持久存儲捲聲明-Persistent Volume Claim,PVC

PV和PVC使得K8s集群具備了存儲的邏輯抽象能力,使得在配置Pod的邏輯里可以忽略對實際後臺存儲技術的配置,而把這項配置的工作交給PV的配置者,即集群的管理者。

存儲的PV和PVC的這種關係,跟計算的Node和Pod的關係是非常類似的;PV和Node是資源的提供者,根據集群的基礎設施變化而變化,由K8s集群管理員配置;而PVC和Pod是資源的使用者,根據業務服務的需求變化而變化,由K8s集群的使用者即服務管理員來配置。

 

節點-Node

K8s集群中的計算能力由Node提供,最初Node稱為服務節點Minion,後來改名為Node。K8s集群中的Node也就等同於Mesos集群中的Slave節點,是所有Pod運行所在的工作主機,可以是物理機也可以是虛擬機。

無論是物理機還是虛擬機,工作主機的統一特征是上面要運行kubelet管理節點。

 

密鑰對象-Secret

Secret是用來保存和傳遞密碼、密鑰、認證憑證這些敏感信息的對象。使用Secret的好處是可以避免把敏感信息明文寫在配置文件里。

在K8s集群中配置和使用服務不可避免的要用到各種敏感信息實現登錄、認證等功能,例如訪問AWS存儲的用戶名密碼。

為了避免將類似的敏感信息明文寫在所有需要使用的配置文件中,可以將這些信息存入一個Secret對象,而在配置文件中通過Secret對象引用這些敏感信息。這種方式的好處包括:意圖明確,避免重覆,減少暴漏機會。

 

用戶帳戶-User Account和服務帳戶-Service Account

顧名思義,用戶帳戶為人提供賬戶標識,而服務賬戶為電腦進程和K8s集群中運行的Pod提供賬戶標識。

用戶帳戶和服務帳戶的一個區別是作用範圍;用戶帳戶對應的是人的身份,人的身份與服務的namespace無關,所以用戶賬戶是跨namespace的;而服務帳戶對應的是一個運行中程式的身份,與特定namespace是相關的。

 

名稱空間-Namespace

名稱空間為K8s集群提供虛擬的隔離作用,K8s集群初始有兩個名稱空間,分別是預設名稱空間default和系統名稱空間kube-system,除此以外,管理員可以創建新的名稱空間滿足需要。

 

RBAC訪問授權

K8s在1.3版本中發佈了alpha版的基於角色的訪問控制(Role-based Access Control,RBAC)的授權模式。相對於基於屬性的訪問控制(Attribute-based Access Control,ABAC),RBAC主要是引入了角色(Role)和角色綁定(RoleBinding)的抽象概念。在ABAC中,K8s集群中的訪問策略只能跟用戶直接關聯;而在RBAC中,訪問策略可以跟某個角色關聯,具體的用戶再跟一個或多個角色相關聯

顯然,RBAC像其他新功能一樣,每次引入新功能,都會引入新的API對象,從而引入新的概念抽象,而這一新的概念抽象一定會使集群服務管理和使用變得更容易擴展和重用。

 

總結

從K8s的系統架構、技術概念和設計理念,我們可以看到K8s系統最核心的兩個設計理念:一個是容錯性,一個是易擴展性

容錯性實際是保證K8s系統穩定性和安全性的基礎;易擴展性是保證K8s對變更友好,可以快速迭代增加新功能的基礎。

 


 

———END———
如果覺得不錯就關註下唄 (-^O^-) !

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 雖然Python的強項在人工智慧,數據處理方面,但是對於日常簡單的應用,Python也提供了非常友好的支持(如:Tkinter),本文主要一個簡單的畫圖小軟體,簡述Python在GUI(圖形用戶界面)方面的應用,僅供學習分享使用,如有不足之處,還請指正。 ...
  • Debug LinkedList源碼 前置知識 LinkedList基於鏈表,LinkedList的Node節點定義 成員變數 //鏈表中元素的數量 transient int size = 0; /** * 鏈表的頭節點:用於遍歷 */ transient Node<E> first; /** * ...
  • 1 int StringSearch(char str[], char strSearch[]) 2 { 3 int i = -1; 4 while (str[i]) 5 { 6 char c = strSearch[0];//鎖定查找字元的第1位置 7 if (str[i] != c)//判斷查找 ...
  • 學習就是為了不斷的看到自己的知識盲點,然後改正,以前知道如何使用break來跳出迴圈,突然學習到可以用break跳出外部的迴圈(以前只知道怎麼調本次的迴圈)。 上正題代碼如下: break跳出本次迴圈: public static void main(String[] args) { for (in ...
  • 功能介紹 客戶端給所有線上用戶發送消息 客戶端給指定線上用戶發送消息 伺服器給客戶端發送消息(輪詢方式) 註意:socket只是實現一些簡單的功能,具體的還需根據自身情況,代碼稍微改造下 項目搭建 項目結構圖 pom.xml <?xml version="1.0" encoding="UTF-8"? ...
  • 本文源碼:GitHub·點這裡 || GitEE·點這裡 一、分支語句 流程式控制制語句對任何一門編程語言都是非常重要的,Java中基於流程式控制製程序執行的不同步驟和代碼塊。 1、IF條件 IF條件語句會根據不同的判斷條件執行不同的語句,if後括弧內的條件是否成立關鍵步驟,IF條件的判斷結果必然要是tru ...
  • 在上篇文章中,我為構建自定義端點可視化圖奠定了基礎,正如我在第一篇文章中展示的那樣。該圖顯示了端點路由的不同部分:文字值,參數,動詞約束和產生結果的端點: 在本文中,我將展示如何通過創建一個自定義的DfaGraphWriter來為自己的應用程式創建一個端點圖。 這篇文章使用了本系列前幾篇文章中的技巧 ...
  • 最近用戶反映一些電腦啟動程式就崩潰,還給演示了一個比較詭異的問題 “把軟體重新拷貝到另外一個目錄,就能正常運行"。還說過一段時間又不能運行需要在換個位置。 ’由於當時沒有設置全局異常,只能藉助系統操作日誌來分析, 系統日誌記錄不全,就說發生一個異常程式掛掉。 就簡單加上全局異常捕獲。 public ...
一周排行
    -Advertisement-
    Play Games
  • 比如要拆分“呵呵呵90909086676喝喝999”,下麵當type=0返回的是中文字元串“呵呵呵,喝喝”,type=1返回的是數字字元串“90909086676,999”, private string GetStrings(string str,int type=0) { IList<strin ...
  • Swagger一個優秀的Api介面文檔生成工具。Swagger可以可以動態生成Api介面文檔,有效的降低前後端人員關於Api介面的溝通成本,促進項目高效開發。 1、使用NuGet安裝最新的包:Swashbuckle.AspNetCore。 2、編輯項目文件(NetCoreTemplate.Web.c ...
  • 2020 年 7 月 30 日, 由.NET基金會和微軟 將舉辦一個線上和為期一天的活動,包括 微軟 .NET 團隊的演講者以及社區的演講者。本次線上大會 專註.NET框架構建微服務,演講者分享構建和部署雲原生應用程式的最佳實踐、模式、提示和技巧。有關更多信息和隨時瞭解情況:https://focu... ...
  • #abp框架Excel導出——基於vue #1.技術棧 ##1.1 前端採用vue,官方提供 UI套件用的是iview ##1.2 後臺是abp——aspnetboilerplate 即abp v1,https://github.com/aspnetboilerplate/aspnetboilerp ...
  • 前言 本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。 作者:碧茂大數據 PS:如有需要Python學習資料的小伙伴可以加下方的群去找免費管理員領取 input()輸入 Python提供了 input() 內置函數從標準輸入讀入一 ...
  • 從12年到20年,python以肉眼可見的趨勢超過了java,成為了當今It界人人皆知的編程語言。 python為什麼這麼火? 網路編程語言搜索指數 適合初學者 Python具有語法簡單、語句清晰的特點,這就讓初學者在學習階段可以把精力集中在編程對象和思維方法上。 大佬都在用 Google,YouT ...
  • 在社會上存在一種普遍的對培訓機構的學生一種歧視的現象,具體表現在,比如:當你去公司面試的時候,一旦你說了你是培訓機構出來的,那麼基本上你就涼了,那麼你瞞著不說,然後又通過了面試成功入職,但是以後一旦在公司被髮現有培訓經歷,可能會面臨被降薪,甚至被辭退,培訓機構出來的學生,在用人單位眼裡就是能力低下的 ...
  • from typing import List# 這道題看了大佬寫的代碼,經過自己的理解寫出來了。# 從最外圍的四周找有沒有為O的,如果有的話就進入深搜函數,然後深搜遍歷# 判斷上下左右的位置是否為Oclass Solution: def solve(self, board: List[List[s ...
  • import requests; import re; import os; # 1.請求網頁 header = { "user-agent":'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, li ...
  • import requests; import re; import os; import parsel; 1.請求網頁 header = { "user-agent":'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537. ...