導航:首頁 > 程序命令 > 重啟k8s的命令

重啟k8s的命令

發布時間:2022-10-09 09:31:27

⑴ K8S常用命令介紹

k8s常用命令:

禁止|恢復node節點調度:
kubectl cordon|uncordon nodename
刪除節點(慎用):
kubectl drain nodename(驅除非系統pod)
kubectl delete nodename (刪除節點)

創建資源:
kubectl create|apply -f file.yaml
create 命令一般用於創建新資源。 因此,如果再次運行該命令,則會拋出錯誤,因為資源名稱在名稱空間中應該是唯一的
apply 命令一般用於更新資源配置。 如果資源不在那裡,那麼它將被創建。 kubectl apply命令可以運行更多次,只要資源定義沒變,資源將不會變動

查看資源列表:
kubectl get node|pod|service|deployment|configmap|... -n namespace [-o wide] [-w]

查看特定資源詳情:
kubectl describe pod podname -n namespace

查看資源定義:
kubectl get deploy deployname -n namespace -o yaml [>file.yaml] 重定向到文件里,可以再次apply -f yaml

編輯資源(只對spec欄位下內容生效):
kubectl edit node|pod|service|deployment|configmap|... -n namespace

刪除資源(慎用):
kubectl delete pod podname -n namespace [--force --grace-period=0] 強制刪除
grace-period表示過渡存活期,默認30s,在刪除POD之前允許POD慢慢終止其上的容器進程,從而優雅退出,0表示立即終止POD

查看pod log:
kubectl logs [-f] podname -n namespace

進入pod(容器),或執行命令:
kubectl exec -it podname -n namespace [-c containername] -- /bin/sh [CMD]
-c 是進入多個容器中的某個指定容器
-- 指的是不用進入容器就可以執行命令

pod擴縮容:k
手動擴縮容:kubectl scale deployment deployname -n namespace --replicas=x;也可用kubectl edit對deployment進行編輯後apply

pod升級與回滾:
deployment:
升級:kubectl set image deployment/deplyname -n namespce image=imagename:xxx; 也可用kubectl edit對deployment進行編輯後apply
更新策略:
Recreate: 更新時先殺掉正在運行的pod,然後創建新的pod
RollingUpdate: 滾動方式進行更新,參數maxUnavailable和maxSurge來控制滾動更新的過程
回滾(不常用):kubectl rollout status|history deployment/deployname -n namespace [--to-revision=x]

pod調度:
NodeName定向調度:通過node節點的主機名進行定向調度
NodeSelector定向調度:通過Node節點標簽和pod資源屬性nodeSelector匹配實現pod的定向調度
查看node節點標簽:
kubectl get node --show-labels
查看指定標簽的節點: kubectl get node -l key=value
節點增加標簽:kubectl label nodes nodename key=value
刪除節點標簽:kubectl label nodes nodename key-
修改節點標簽: kubectl label nodes nodename key=newvalue --overwrite

⑵ k8s 基本使用(上)

本文將介紹 k8s 中的一些最基本的命令,並輔以解釋一些基本概念來方便理解,也就是說,本文是一篇偏向實用性而非學術性的文章,如果你想提前了解一下 k8s 相關的知識的話,可以通過以下鏈接進行學習:

k8s 是經典的一對多模型,有一個主要的管理節點 master 和許多的工作節點 slaver 。當然,k8s 也可以配置多個管理節點,擁有兩個以上的管理節點被稱為 高可用 。k8s 包括了許多的組件,每個組件都是單運行在一個 docker 容器中,然後通過自己規劃的虛擬網路相互訪問。你可以通過 kubectl get pod -n kube-system 查看所有節點上的組件容器。

在管理節點中會比工作節點運行更多的 k8s 組件,我們就是靠著這些多出來的組件來對工作節點發號施令。他們都叫什麼這里就不詳細提了。反正對於」基本使用「來說,這些名字並不重要。

要想理解一個東西就要先明白它的內在理念。通俗點就是,k8s 做了什麼?為了提供更加可靠的服務,就要增加伺服器的數量,減少每個伺服器的體量來平攤負載,而越來越多的虛擬機就會帶來越來越高的運維成本。如何讓少量的運維人員就可以管理數量眾多的伺服器及其上的服務呢?這就是 k8s 做的工作。

k8s 把數量眾多的伺服器重新抽象為一個統一的資源池 ,對於運維人員來說,他們面前沒有伺服器1、伺服器2的概念,而是一個統一的資源池,增加新的伺服器對運維人員來說,只是增加自資源池的可用量。不僅如此,k8s 把所有能用的東西都抽象成了資源的概念,從而提供了一套更統一,更簡潔的管理方式。

接下來,我會把每個基本命令當做一節來進行介紹,並輔以介紹一些基本概念。本文介紹的命令涵蓋了增刪改查四方面,可參加下面表格,因為篇幅較長,我們將 create 及之後的不那麼常用的命令放在下一篇文章 k8s 基本使用(下) 里講:

接下來進入正題,首先來了解一下 k8s 中最最最常用的命令 kubectl get ,要記住,k8s 把所有的東西都抽象成了資源,而 kubectl get 就是用來查看這些資源的。最常見的資源就是 pod 。

不僅我們自己的服務是要包裝成 pod 的,就連 k8s 自己也是運行在一堆 pod 上。接下來就讓我們查看一下 k8s 的 pod :

-n 參數指定了要查看哪個命名空間下的 pod 。 k8s 所有的 pod 都被放置在 kube-system 命名空間下。

執行了 kubectl get pod -n kube-system 命令後,你就可以看到如下內容:

其中每一行就是一個資源,這里我們看到的資源是 pod 。你看到的 pod 數量可能和我的不一致,因為這個列表裡包含了 k8s 在所有節點上運行的 pod ,你加入的節點越多,那麼顯示的 pod 也就越多。我們來一列一列的看:

kubectl get 可以列出 k8s 中所有資源

這里只介紹了如何用 kubectl 獲取 pod 的列表。但是不要把 get 和 pod 綁定在一起,pod 只是 k8s 中的一種服務,你不僅可以 get pod ,還可以 get svc ( 查看服務 )、 get rs ( 查看副本控制器 )、 get deploy ( 查看部署 )等等等等,雖然說 kubectl get pod 是最常用的一個,但是如果想查看某個資源而又不知道命令是什麼, kbuectl get <資源名> 就對了。

如果你想看更多的信息,就可以指定 -o wide 參數,如下:

加上這個參數之後就可以看到資源的所在 ip 和所在節點 node 了。

記得加上 -n

-n 可以說是 kubectl get 命令使用最頻繁的參數了,在正式使用中,我們永遠不會把資源發布在默認命名空間。所以,永遠不要忘記在 get 命令後面加上 -n 。

kubectl get 命令可以列出 k8s 中的資源,而 kubectl get pod 是非常常用的查看 pod 的命令。而 -n 參數則可以指定 pod 所在的命名空間。

kubectl describe 命令可以用來查看某一資源的具體信息,他同樣可以查看所有資源的詳情, 不過最常用的還是查看 pod 的詳情 。他也同樣可以使用 -n 參數指定資源所在的命名空間。

舉個例子,我們可以用下面命令來查看剛才 pod 列表中的某個 pod,注意不要忘記把 pod 名稱修改成自己的:

然後你就可以看到很多的信息,咱們分開說,首先是基本屬性,你可以在詳細信息的開頭找到它:

基本屬性

其中幾個比較常用的,例如 Node 、 labels 和 Controlled By 。通過 Node 你可以快速定位到 pod 所處的機器,從而檢查該機器是否出現問題或宕機等。通過 labels 你可以檢索到該 pod 的大致用途及定位。而通過 Controlled By ,你可以知道該 pod 是由那種 k8s 資源創建的,然後就可以使用 kubectl get <資源名> 來繼續查找問題。例如上文 DaemonSet/kube-flannel-ds-amd64 ,就可以通過 kubectl get DaemonSet -n kube-system 來獲取上一節資源的信息。

內部鏡像信息

在中間部分你可以找到像下面一樣的 Containers 段落。該段落詳細的描述了 pod 中每個 docker 容器的信息,常用的比如 Image 欄位,當 pod 出現 ImagePullBackOff 錯誤的時候就可以查看該欄位確認拉取的什麼鏡像。其他的欄位名都很通俗,直接翻譯即可。

事件

在 describe 查看詳情的時候,最常用的信息獲取處就是這個 Event 段落了,你可以在介紹內容的末尾找到它,如下:

是的,如果你看到上面這樣,沒有任何 Events 的話,就說明該 pod 一切正常。當 pod 的狀態不是 Running 時,這里一定會有或多或少的問題,長得像下面一樣,然後你就可以通過其中的信息分析 pod 出現問題的詳細原因了:

kubectl describe <資源名> <實例名> 可以查看一個資源的詳細信息,最常用的還是比如 kubectl describe pod <pod名> -n <命名空間> 來獲取一個 pod 的基本信息。如果出現問題的話,可以在獲取到的信息的末尾看到 Event 段落,其中記錄著導致 pod 故障的原因。

如果你想查看一個 pod 的具體日誌,就可以通過 kubectl logs <pod名> 來查看。注意,這個只能查看 pod 的日誌。通過添加 -f 參數可以持續查看日誌。例如,查看 kube-system 命名空間中某個 flannel pod 的日誌,注意修改 pod 名稱:

然後就可以看到如下輸出:

如果你發現某個 pod 的服務有問題,但是狀態還是顯示 Running ,就可以使用 kubectl logs 來查看其詳細日誌。

在本篇文章里,我們了解了 k8s 的宗旨和一些基本概念,並知道了最為常用的 get 、 descibe 及 logs 命令,知道了這三條命令之後就幾乎可以從 k8s 中獲取所有常用信息了。接下來的 k8s 基本使用(下) 里,我們會更深一步,來了解 k8s 中如何創建、修改及刪除資源。

⑶ k8s常用命令

命令行 敲出的指令分為2種,

資源管理方式分類

直接使用命令去操作k8s資源,命令和參數一起出現

通過命令和配置文件去操作作k8s資源,命令還是那個命令,只不過參數都放在配置文件裡面

使用apply創建資源,

說明

在master節點執行以下命令即可刪除

還需要在work節點上執行以下命令來清空ini配置

先在主節點創建令牌

然後在需要加入集群的節點中執行令牌,注意這里的命令是通過 kubeadm token create --print-join-command 命令返回的結果

說明

記住,名稱中不能用下劃線 _ ,可以用橫行 - 第一種創建方式–命令行創建

第二種創建方式–命令行 + 配置文件
創建一個名為namespace-dev.yaml的文件,內容如下(注意大小寫,kind的頭字母必須大寫)

然後偶執行命令進行創建

需要注意的是,刪除後,當前命名空間下的pod、deployment、 container 也會一起刪掉

第一種–使用命令刪除

第二種–使用配置文件刪除

說明

獲取所有namespace的pod並監視資源變動
加上 -w 表示監視資源變動信息,此時命令行進入阻塞狀態,如果pod有變化將會馬上呈現出來;

其他參數

因為pod裡面至少要有一個容器,所以pod是和容器一起創建的,新建一個文件 pod.ymal ,內容如下

然後執行命令並指定配置文件進行創建

以下示例是為pod資源打標簽,這種方式是和pod一起創建的,新建一個配置文件 label.yaml

執行命令創建pod

適合更新label值,前提是label的key必須已存在;

刪除key為lebelKey的標簽

pod控制器有很多種,我們這里就用deployment

使用以下run命令運行一個nginx,deployment名稱為 app=run-cmd-nginx-deploy-3

通過以下命令可以看到,會自動生成一個 app=run-cmd-nginx-deploy-3 的標簽

新建一個deployment.yaml文件,內容如下

需要注意的是,一旦刪除pod控制器,此pod控制器下的所有pod和容器也會一並刪除;

默認創建的pod是只能對內訪問的,所以需要創建一個對外的訪問埠,創建一個service其實就是暴露對外的訪問埠

說明

創建好service之後,查看service信息,可以看到,暴露的埠為:30474,

新建一個service.ymal文件,內容如下

以下三種用法都可以

查詢pod控制器和pod

Endpoint是kubernetes中的一個資源對象,存儲在etcd中,用來記錄一個service對應的所有pod的訪問地址,它是根據service配置文件中selector描述產生的。

一個Service由一組Pod組成,這些Pod通過Endpoints暴露出來,Endpoints是實現實際服務的端點集合。換句話說,service和pod之間的聯系是通過endpoints實現的。

每創建一個service,k8s會自動創建一個同名的 Endpoint出來

如果是由service創建出來的endpoints,刪除後會馬上創建出一個同名的endpoint出來,如果要刪除必須先刪除service

因為每次創建一個service,k8s會自動創建一個同名的 Endpoint出來,所我們直接創建service就可以了

--help 用來查看幫助文檔,如果你不知道某個命令怎麼使用了,就可以用 --help 查詢命令的用法

explain用來查看配置文件的 資源結構,如果不知道配置文件中的資源用有哪些結構,那麼就可以使用explain命令來查看

linux裡面k8s裡面kind:service代表什麼意思

1 Service 含義
K8s service可以理解為對一組Pod的抽象。類似於Nginx能夠把請求轉發 的 對應的服務上。
2 Service作用

2.1 pod使用時因某些問題重啟,從而導致pod 的IP發生變化,會導致舊的IP不能用,影響用戶對系統使用。service的出現很好 的 解決此問題,客戶端通過service 訪問pod,當podIP有變化也不會影響(service通過Label Selector跟pod綁定)。
2.2 對外暴露pod訪問請求埠。
2.3 固定IP。
2.4 負載均衡。
3 Service 工作機制
3.1 userspace代理模型流程
userspace指Linux操作系統的用戶空間(物理上為內存)。對於service會對外暴露埠號,用戶空間中的kube-proxy會監控service埠上請求,並把請求轉發到對應的pod上。
請求到達內核空間後經由套接字送往用戶空間的kube-proxy,並調度至後端pod。請求會在內核和用戶空間之間來回轉發導致效率不高。(如下圖)
3.2 iptables代理模型流程
kube-proxy負責跟蹤API Server上的Service和Endpoints對象的變動,並根據變動做出iptables的變動。
iptables捕捉到達clusterIP與埠的請求,並將請求轉發到當前service後端pod。
iptables模型不用將流量在用戶空間和內核空間來回切換,因而更加高效和可靠,不過其缺點是iptables代理模型不會在被挑中的後端Pod資源無響應時進行重定向。
3.3 ipvs代理模型
K8s從1.9版本引入ipvs代理模型,且從1.11版本起成為默認設置。
它和iptables模型很類似,唯一一點不同的是在其請求流量的調度功能由ipvs實現,餘下的功能仍由iptables完成。
ipvs是建立在netfilter的鉤子函數上,但它使用hash表作為底層數據結構並工作於內核空間,因此流量轉發速度特別快、規則同步性很好,
而且它支持眾多調度演算法,rr(輪詢)、lc(最小連接數)、dh(目標哈希)、sh(源哈希)、sed(最短期望延遲)、nq(不排隊調度)。
3 Service 類型
3.1 ClusterIp:默認類型,自動分配一個僅Cluster內部可以訪問的虛擬IP.
3.2 NodePort:在ClusterIP基礎上為Service在每台機器上綁定一個埠,這樣可以通過NodeIP:NodePort來訪問服務。
也可以這樣理解在於在 node 上暴露了一個埠,將向該埠的流量導入到 kube-proxy,然後由 kube-proxy 進一步到給對應的 pod。
k8s配置好對外訪問埠後,linux防火牆也需要通過命令配置(-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT)
3.3 LoadBalancer:在NodePort基礎上,藉助cloud provider創建一個外部負載均衡器,並將請求轉發到NodeIP:NodePort。
另一種理解調用cloud provider 去創建 LB 來向節點導流
3.4 ExternalName: 把集群外部的服務引入到集群內部來,在集群內部直接使用,沒有任何類型代理被創建,這只有kubernetes1.7 或更高版本的kube-dns才支持
4 port nodePort targetPod 區別
4.1 port service暴露在cluster ip上的埠,<cluster ip>:port 是提供給集群內部客戶訪問service的入口
4.2 nodePort 是kubernetes提供給集群外部客戶訪問service入口的一種方式(另一種方式是LoadBalancer),所以,<nodeIP>:nodePort 是提供給集群外部客戶訪問service的入口.
4.3 targetPort 是pod上的埠,從port和nodePort上到來的數據最終經過kube-proxy流入到後端pod的targetPort上進入容器

4 Service腳本創建
apiVersion: v1
kind: Service
metadata:
name: myService
spec:
selector:
app: tomcat
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
selector欄位中指定了為哪一個標簽的app進行負載均衡即暴露pod 的name為tomcat對外的訪問埠。

⑸ k8s 網路基礎

author:sufei
說明:本文主要記錄在學習k8s網路方面的相關知識

 Linux在內核網路棧中引入網路命名空間,將 獨立的網路協議棧隔離 到不同的命令空間中,彼此間無法通信;

1、Linux操作系統,解析和封裝網路包是通過一個網路協議棧完成,下層為上層服務,這個 協議棧中即包括如軟體也包括硬體網路設 備。網路命名空間就是以軟體方式隔離出單獨的網路棧信息;

2、不同network namespace的軟硬體資源相互不可見,好像處在物理隔離的不同物理機上一樣,彼此隔離;

3、不同的網路命名空間會有自己獨立的網卡、路由表、ARP 表、iptables 等和網路相關的資源

4、實驗:可以藉助 ip netns 命令來完成對 Network Namespace 的各種操作,如:

問題 :什麼是轉移設備?

 可以在不同的 Network Namespace 之間轉移設備(如veth)。由於一個設備只能屬於一個 Network Namespace ,所以轉移後在這個 Network Namespace 內就看不到這個設備了。 veth設備屬於可轉移設備 ,而很多其它設備(如lo、bridge等)是不可以轉移的。

 veth pair 全稱是 Virtual Ethernet Pair,是一個成對的埠,所有從這對埠一 端進入的數據包都將從另一端出來,反之也是一樣。而veth pair就是為了在不同的 Network Namespace 直接進行通信,利用它可以直接將兩個 Network Namespace 連接起來。

實驗

 veth pair打破了 Network Namespace 的限制,實現了不同 Network Namespace 之間的通信。但veth pair有一個明顯的缺陷,就是只能實現兩個網路介面之間的通信。如果我們想實現多個網路介面之間的通信,就可以使用下面介紹的網橋(Bridge)技術( 類似於物理交換機 )。
 簡單來說,網橋就是把一台機器上的若干個網路介面「連接」起來。其結果是,其中一個網口收到的報文會被復制給其他網口並發送出去。以使得網口之間的報文能夠互相轉發。

 網橋是一個二層網路設備,通過網橋可以將linux支持的不同的埠連接起來,並實現類似交換機那樣的多對多的通信。

實驗:

 Netfilter負責在內核中執行各種掛接的規則(過濾、修改、丟棄等),運行在內核 模式中;Iptables模式是在用戶模式下運行的進程,負責協助維護內核中Netfilter的各種規則表;通過二者的配合來實現整個Linux網路協議棧中靈活的數據包處理機制。

 iptables/netfilter(簡稱iptables)組成了Linux平台下的包過濾防火牆,可以完成封包過濾、封包重定向和網路地址轉換(NAT)等功能。這部分主要了解兩部分知識:

 應用層不管是要發送還是接收網路消息,都需要通過linux內核提供的一系列關卡。每個」關卡「擔負著不同的工作。這里的」關卡「被稱為」鏈「。如下圖:

 Docker啟動一個容器時會根據Docker網橋的網段分配給容器一個IP地址,稱為Container-IP,同時Docker網橋是每個容器的默認網關(如上面的172.17.0.1)。因為在同一宿主機內的容器都接入同一個網橋,這樣容器之間就能夠通過容器的Container-IP直接通信。

 Docker網橋是宿主機虛擬出來的,並不是真實存在的網路設備,外部網路是無法定址到的,這也意味著外部網路無法通過直接Container-IP訪問到容器。如果容器希望外部訪問能夠訪問到,可以通過映射容器埠到宿主主機(埠映射),即docker run創建容器時候通過 -p 或 -P 參數來啟用,訪問容器的時候就通過[宿主機IP]:[容器埠]訪問容器。

 下面具體來說說docker容器的幾種網路模式,以便後續學習k8s網路。

 在host模式下( –net=host),容器不會去建立新的網路命名空間,而直接使用宿主機的網路設備以及網路協議棧。這樣自然不會虛擬出自己的網卡,配置自己的IP等。其特點如下:

 這個模式就是在創建容器時,指定網路(–net=container:NAME_or_ID)與之前容器在同一個網路命名空間中,而不是和宿主機共享(這也就是k8s中pod內各容器的一種網路模式)。下面說明幾點:

 none模式(–net=none)Docker容器擁有自己的Network Namespace,但是,並不為Docker容器進行任何網路配置。也就是說,這個Docker容器沒有網卡、IP、路由等信息。需要我們自己為Docker容器添加網卡、配置IP等。

 bridge模式是docker容器的默認模式,當Docker進程啟動時,會在主機上創建一個名為docker0的虛擬網橋,此主機上啟動的Docker容器在bridge模式下會連接到這個虛擬網橋上,並由網橋自動分配ip。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網路中。

 下面說明這個模式下的工作方式:

 首先我們來看看k8s想要一個什麼樣的網路,也就是k8s網路設計的要求,具體如下:

 下面簡單從幾中不同的通信要求來看看k8s網路實現。

 在 Kubernetes 的世界裡,IP 是以 Pod 為單位進行分配的。一個 Pod 內部的所有容器共享一個網路堆棧。實際上就是docker container網路模式。可以直接通過本地localhost進行網路訪問。這個模式在mysql容器化中就是agent容器與mysql容器的網路通信方式。

 Pod1和Pod2都是通信veth pair連接到同一個docker0網橋上,它們的IP地址都是從docker0網段上動態獲取的,它們和網橋本身的IP是同一個網段的。可以通過docker0作為交換機進行通信,也就是採用的docker bridge網路模式進行通信。

 由於在同一個網橋docker0上即可以保證分配的pod IP不會沖突,且可以相互通信,而如果需要跨Node物理節點,則無法通過docker網路直接滿足要求了,那這些要求具體有哪些呢?

解決方案

方法一:k8s中通過在etcd中記錄正在運行中pod的IP分配信息,這樣我們就可以滿足Pod IP與Node IP之間映射關系的記錄;

方法二:可以在etcd中規劃配置好所有主機docker0網橋的子網范圍,從而滿足Pod IP不沖突的要求;如:

方法三:要實現Pod跨Node通信,以k8s默認網路Flannel為例,就是採用overlay(覆蓋網路)實現。具體下面說明:

問題:什麼是覆蓋網路?

覆蓋網路就是應用層網路,是指建立在另一個網路上的網路。怎麼理解呢?簡單理解就是將TCP數據包裝在另一種網路包裡面進行路由轉發和通信,另一種網路包目前可以是UDP、VxLAN、AWS VPC和GCE路由等數據轉發方式。默認以UDP為例來說明flannel工作方式。

下面看看具體實現

問題 :為保證各node內docker容器分配的ip地址不沖突,每個節點上的Docker會使用不同的IP地址段?如何實現的呢?

問題 :為什麼在發送節點上的數據會從docker0路由到flannel0虛擬網卡,在目的節點會從flannel0路由到docker0虛擬網卡?

⑹ K8S有什麼作用

K8s在什麼情況會殺掉服務?使用Rancher來運行Kubernetes有很多優勢。大多數情況下能使用戶和IT團隊部署和管理工作更加方便。Rancher自動在Kubernetes後端實現etcd 的HA,並且將所需要的服務部署到此環境下的任何主機中。在設置訪問控制,可以輕易連接到現有的LDAP和AD基礎構架。Rancher還可以自動實現容器聯網以及為Kubernetes提供負載均衡服務。通過使用Rancher,你將會在幾分鍾內有擁有Kubernetes的HA實現。命名空間現在我們的集群已經運行了,讓我們進入並查看一些基本的Kubernetes資源吧。你可以訪問Kubernetes集群也可以直接通過kubectl CLI訪問,或者通過Rancher UI 訪問。Rancher的訪問管理圖層控制可以訪問集群,所以你需要在訪問CLI前從Rancher UI那裡生成API密匙。我們來看下第一個Kubernetes資源命名空間,在給定的命名空間中,所有資源名稱必須有唯一性。此外,標簽是用來連接劃定到單個命名空間的資源。這就是為什麼同一個Kubernetes集群上可以用命名空間來隔離環境。例如,你想為應用程序創建Alpha, Beta和生產環境,以便可以測試最新的更改且不會影響到真正的用戶。最後創建命名空間,復制下面的文本到namespace.yaml文件,並且運行 kubectl -f namespace.yaml 命令,來創建一個beta命名空間。kind: NamespaceapiVersion: v1metadata:name: betalabels:name: beta當然你還可以使用頂部的命名空間菜單欄從Rancher UI上創建、查看和選擇命名空間。你可以使用下面的命令,用kubectl來為CLI交互設置命名空間:$ kubectl config set-context Kubernetes --namespace=beta.為了驗證目前context是否已經被設置好,你可以使用config view命令,驗證一下輸出的命名空間是否滿足你的期望。$ kubectl config view | grep namespace command namespace: betaPods現在我們已經定義好了命名空間,接下來開始創建資源。首先我們要看的資源是Pod。一組一個或者多個容器的Kubernetes稱為pod,容器在pod 里按組來部署、啟動、停止、和復制。在給定的每個主機種類里,只能有一個Pod,所有pod里的容器只能在同一個主機上運行,pods可以共享網路命名空間,通過本地主機域來連接。Pods也是基本的擴展單元,不能跨越主機,因此理想狀況是使它們盡可能接近單個工作負載。這將消除pod在擴展或縮小時產生的副作用,以及確保我們創建pods不太耗資源而影響到主機。我們來給名為mywebservice的pod定義,在規范命名web-1-10中它有一個容器並使用nginx容器鏡像,然後把埠為80下的文本添加至pod.yaml文檔中。apiVersion: v1kind: Podmetadata:name: mywebservicespec:containers:- name: web-1-10image: nginx:1.10ports:- containerPort: 80使用kubetl create命令創建pod,如果您使用set-context command設置了您的命名空間,pods將會在指定命名空間中被創立。在通過運行pods命令去驗證pod狀態。完成以後,我們可以通過運行kubetl delete命令刪除pod。$ kubectl create -f ./pod.yamlpod "mywebservice" created$ kubectl get podsNAME READY STATUS RESTARTS AGEmywebservice 1/1 Running 0 37s$ kubectl delete -f pod.yamlpod "mywebservice" deleted在Rancher UI 中查看pod,通過頂端的菜單欄選擇 Kubernetes > Pods 。

⑺ K8S安裝和創建集群終極教程(單master多worker)

本文會以 最簡單 最直接 最完整 的方式記錄kubernetes(下面統稱K8S)單master多工作節點(worker nodes)的集群步驟

首先要簡單了解一下本文的3個核心概念:

內存建議至少4G

問:如何查看主機名?

答:執行命令hostname

問:如何修改主機名?

答:永久生效的做法:執行命令vi /etc/hostname,把第一行去掉(不能注釋掉,要去掉),然後重新寫上自定義的主機名(注意命名規范),保存並重啟後生效;

臨時生效的做法:執行以下命令

問:如何查看MAC地址?

答:執行命令ip link,然後看你的第一網卡

問:如何查看proct_uuid?

答:執行命令sudo cat /sys/class/dmi/id/proct_uuid

注意:30000-32767這個埠范圍是我們創建服務的埠必須要設置的一個范圍(如果設置范圍以外的會有限制提示並創建失敗),這是K8S規定的。

另外,如果你要直接關閉防火牆可以執行

⑥必須禁用Swap

Swap total大於0,說明Swap分區是開啟的

問:如何關閉Swap?

答:編輯文件/etc/fstab,在swap行前面加上#號注釋, 保存並重啟伺服器

再次查看分區狀態,已生效

常見的容器引擎(Container runtime,簡稱runtime):

本文使用的容器引擎是Docker

安裝完成後查看版本:

當出現可能跟Docker引擎相關的奇怪異常時可以嘗試把Docker卸載干凈並重新安裝,但一定要注意鏡像、容器、卷或配置文件這些是否需要備份。

下面記錄卸載Docker引擎的步驟:

①卸載 Docker Engine、CLI 和 Containerd 包:

②主機上的映像、容器、卷或自定義配置文件不會自動刪除。刪除所有鏡像、容器和卷:

③配置文件如果有不合法的字元時會導致啟動失敗,我們需要將其刪除然後重建

此時Docker引擎已卸載干凈

官網用的是谷歌的yum源,因為國內是連不上的,所以這里替換成阿里提供的yum源

①安裝

從安裝信息中可以看到版本號是1.22

Installing:

kubeadm x86_64 1.22.4-0 kubernetes 9.3 M

kubectl x86_64 1.22.4-0 kubernetes 9.7 M

kubelet x86_64 1.22.4-0 kubernetes 20 M

②啟動



這就是一個驅動程序,注意cgroup和cgroupfs不要混淆了

引用官方的一段話

「由於 kubeadm 把 kubelet 視為一個系統服務來管理,所以對基於 kubeadm 的安裝, 我們推薦使用 systemd 驅動,不推薦 cgroupfs 驅動。」

kubeadm默認是使用systemd 驅動,而我們的Docker默認驅動是cgroupfs(docker info可以查看),所以需要將Docker的驅動改成systemd

①編輯Docker配置文件

②重啟Docker服務

再次docker info查看驅動信息已變成了systemd

工作節點(worker nodes)的最小配置就到這里了

①鏡像源參數說明

默認情況下, kubeadm 會從 k8s.gcr.io 倉庫拉取鏡像,國內是拉不了的。官方文檔明確表示允許你使用其他的 imageRepository 來代替 k8s.gcr.io。

--image-repository 你的鏡像倉庫地址

接下來我找了一些國內的鏡像源,並簡單做了下分析

綜合上述統計,我選擇阿里雲的鏡像源

②ip地址范圍參數說明

--pod-network-cidr =192.168.0.0/16

注意:如果192.168.0.0/16已經在您的網路中使用,您必須選擇一個不同的pod網路CIDR,在上面的命令中替換192.168.0.0/16。

集群初始化命令:

因為我用的是演示機器,所以這里把完整的執行信息都貼出來方便查閱,平時工作中一定要注意保護好敏感的信息(我的ip地址范圍是自定義的便於下面的功能演示,另外初次init需要下載鏡像文件,一般需要等幾分鍾)

如上所示,集群初始化成功,此時一定要注意看上面執行結果最後的那部分操作提示,我已用標明了初始化成功後還需要執行的3個步驟

注意:如果init成功後發現參數需要調整,可以執行kubeadm reset,它的作用是盡最大努力恢復kubeadm init 或者 kubeadm join所做的更改。

To start using your cluster, you need to run the following as a regular user:

翻譯:開始使用集群前,如果你是普通用戶(非root),你需要執行以下的命令:

Alternatively, if you are the root user, you can run:

翻譯:或者,如果你使用的是root,你可以執行以下命令:

(注意:export只是臨時生效,意味著每次登錄你都需要執行一次)

網路配置配的就是Pod的網路,我的網路插件選用calico

cidr就是ip地址范圍,如果您使用 pod CIDR 192.168.0.0/16,請跳到下一步。

但本文中使用的pod CIDR是192.100.0.0/16,所以我需要取消對清單中的 CALICO_IPV4POOL_CIDR 變數的注釋,並將其設置為與我選擇的 pod CIDR 相同的值。(注意一定要注意好格式,注意對齊)

可根據需求自定義清單,一般不需要的就直接跳過這步

在所有的工作節點上執行join命令(復制之前初始化成功後返回的加入集群命令到所有的工作節點執行即可)

master上查看所有節點的狀態

到這里集群已經創建完成

最後我再安裝K8S的可視化界面kubernetes-dashboard,方便我們日常使用

①下載yaml文件

②修改yaml文件,新增type和nodePort,使服務能夠被外部訪問

③安裝並查看運行情況

④新建用戶

文件創建完成後保存並apply

⑤獲取Token,用於界面登錄

⑥登錄dashboard

192.168.189.128是我的master伺服器ip,另外要注意必須使用https,並且不能使用ie內核模式

復制⑤生成的token到輸入框,點擊登錄

dashboard安裝配置完成

問:如何在查看資源情況?

答:在master上執行以下命令可查看資源情況(-o wide是顯示更詳細的信息),

①查看所有節點

②查看所有命名空間

③查看命名空間下的pod

④查看所有命名空間的pod

⑤實時查看查看命名空間下的pod運行情況

問:kubeadm join 出現異常[ERROR Port-10250]: Port 10250 is in use,如何解決?

答:這是因為你之前join失敗過了,需要先執行kubeadm reset再重新join

問:虛擬機上測試時網卡突然消失如何解決(題外問題記錄)?

答:

①確認丟失的網卡信息,ens開頭(可選步驟)

ifconfig -a

②執行以下命令解決

問:如何查看K8S版本?

答:kubectl version

問:join命令忘記或者過期了怎麼辦?

答:

生成永不過期的

生成時效24小時的

問:Pod不斷重啟並且無其它報錯信息時怎麼辦?

答:這種情況通常是因為你的集群中只有master,沒有worker節點,master的創建默認是有污點的,即不允許調度新的Pod,如果你需要(當然這並不推薦),就需要刪除 master 上的污點。刪除污點可以執行以下命令,

它應該返回以下內容。

⑻ k8s如何管理服務

聲明式資源清單
陳述式命令
dashboard儀表盤管理
基於其他k8s二次開發的管理工具

⑼ 什麼是K8S



k8s是什麼?

Kubernetes 是一個可移植的,可擴展的開源容器編排平台,用於管理容器化的工作負載和服務,方便了聲明式配置和自動化。它擁有一個龐大且快速增長的生態系統。Kubernetes 的服務,支持和工具廣泛可用。

為什麼現在流行使用容器?

早期: 在物理伺服器上面部署應用程序存在資源分配問題,因為其不能在物理伺服器中的應用程序定義資源邊界,導致應用程序資源利用不足而無法擴展.

後來: 為了解決該問題,引入了虛擬化技術, 虛擬化技術是指允許你在單個物理伺服器的 CPU 上運行多個虛擬機,可以讓多個應用程序在虛擬機之間進行隔離,具有一定的安全性, 每一個虛擬機就是一台完整的計算機, 在虛擬化硬體之上運行所有組件.

現在: 多數在物理伺服器上面部署應用程序都是采kubectl用容器的方式,容器類似於虛擬機,它們都具有自己的文件系統、CPU、內存、進程空間等, 且由於它們與基礎架構分離,因此可以跨雲和 OS 發行版本進行移植。基於此特點被企業大范圍使用.

為什麼需要使用k8s容器?

若出現這樣一個環境: 在生產環境中如果一個容器發生故障,則我們需要手動去啟動另外一個容器,這樣的操作是對我們的管理員來說是不太方便的, 若一個容器出現故障,另一個容器可以自動啟動容器接管故障的容器,這樣是最好的.

k8s就可以實現該效果,Kubernetes 提供了一個可彈性運行分布式系統的框架。 Kubernetes 會滿足你的擴展要求、故障轉移、部署模式等。

k8s功能: 服務發現和負載均衡, 存儲編排, 自動部署和回滾, 自動完成裝箱計算, 自我修復, 密鑰與配置管理

名詞解釋

secret

Secret有三種類型:

k8s的組成

k8s是由組件,API,對象等組成.

包含所有相互關聯組件的 Kubernetes 集群圖如下:

組件


API

Kubernetes 控制面 的核心是 API 伺服器。 API 伺服器負責提供 HTTP API,以供用戶、集群中的不同部分和集群外部組件相互通信。

對象

Kubernetes對象是Kubernetes系統中的持久實體。Kubernetes使用這些實體來表示集群的狀態.

具體來說,他們可以描述:

Kubernetes 架構

Kubernetes 架構由節點,控制面到節點通信, 控制器, 雲控制器管理器組成.

master 流程圖


節點

節點可以是一個虛擬機或者物理機器,取決於所在的集群配置。 每個節點包含運行 Pods 所需的服務, 這些 Pods 由 控制面 負責管理.

節點上的組件包括 kubelet、 容器運行時以及 kube-proxy。

節點狀態

可以使用 kubectl 來查看節點狀態和其他細節信息:

kubectl describe node <�節點名稱>

一個節點包含以下信息:

控制面到節點通信

控制器

在 Kubernetes 中,控制器通過監控集群 的公共狀態,並致力於將當前狀態轉變為期望的狀態。

舉個例子: 當前室內溫度為20度, 我們通過調節遙控器,使其溫度上升至24度, 這20度到24度的變化即為讓其從當前狀態接近期望狀態。

控制器模式分為直接控制和通過API伺服器來控制.

雲控制器管理器

雲控制器管理器是指嵌入特定雲的控制邏輯的 控制平面組件。 雲控制器管理器允許您鏈接聚合到雲提供商的應用編程介面中, 並分離出相互作用的組件與您的集群交互的組件。

雲控制器管理器中的控制器包括:

Kubernetes 安全性

雲原生安全

雲原生安全4個C: 雲(Cloud)、集群(Cluster)、容器(Container)和代碼(Code)

雲原生安全模型的每一層都是基於下一個最外層,代碼層受益於強大的基礎安全層(雲、集群、容器)。我們無法通過在代碼層解決安全問題來為基礎層中糟糕的安全標准提供保護。

基礎設施安全

Kubetnetes 基礎架構關注領域

建議

通過網路訪問 API 服務(控制平面)

所有對 Kubernetes 控制平面的訪問不允許在 Internet 上公開,同時應由網路訪問控制列表控制,該列表包含管理集群所需的 IP 地址集。

通過網路訪問 Node(節點)

節點應配置為 僅能 從控制平面上通過指定埠來接受(通過網路訪問控制列表)連接,以及接受 NodePort 和 LoadBalancer 類型的 Kubernetes 服務連接。如果可能的話,這些節點不應完全暴露在公共互聯網上。

Kubernetes 雲訪問提供商的 API

每個雲提供商都需要向 Kubernetes 控制平面和節點授予不同的許可權集。為集群提供雲提供商訪問許可權時,最好遵循對需要管理的資源的最小特權原則。Kops 文檔提供有關 IAM 策略和角色的信息。

訪問 etcd

對 etcd(Kubernetes 的數據存儲)的訪問應僅限於控制平面。根據配置情況,你應該嘗試通過 TLS 來使用 etcd。更多信息可以在 etcd 文檔中找到。

etcd 加密

在所有可能的情況下,最好對所有驅動器進行靜態數據加密,但是由於 etcd 擁有整個集群的狀態(包括機密信息),因此其磁碟更應該進行靜態數據加密。

集群組件安全

容器安全

代碼安全

Kubernetes架構常見問題

Kubernetes ATTACK 矩陣

信息泄露

雲賬號AK泄露

API憑證(即阿里雲AccessKey)是用戶訪問內部資源最重要的身份憑證。用戶調用API時的通信加密和身份認證會使用API憑證.

API憑證是雲上用戶調用雲服務API、訪問雲上資源的唯一身份憑證。

API憑證相當於登錄密碼,用於程序方式調用雲服務API.

k8s configfile泄露

kubeconfig文件所在的位置:

$HOME/.kube/config

Kubeconfig文件包含有關Kubernetes集群的詳細信息,包括它們的位置和憑據。

雲廠商會給用戶提供該文件,以便於用戶可以通過kubectl對集群進行管理. 如果攻擊者能夠訪問到此文件(如辦公網員工機器入侵、泄露到Github的代碼等),就可以直接通過API Server接管K8s集群,帶來風險隱患。

Master節點SSH登錄泄露

常見的容器集群管理方式是通過登錄Master節點或運維跳板機,然後再通過kubectl命令工具來控制k8s。

雲伺服器提供了通過ssh登陸的形式進行登陸master節點.

若Master節點SSH連接地址泄露,攻擊者可對ssh登陸進行爆破,從而登陸上ssh,控制集群.

容器組件未鑒權服務

Kubernetes架構下常見的開放服務指紋如下:

注:前六個重點關注: 一旦被控制可以直接獲取相應容器、相應節點、集群許可權的服務

了解各個組件被攻擊時所造成的影響

組件分工圖:

假如用戶想在集群裡面新建一個容器集合單元, 流程如下:

  1. 用戶與 kubectl進行交互,提出需求(例: kubectl create -f pod.yaml)
  2. kubectl 會讀取 ~/.kube/config 配置,並與 apiserver 進行交互,協議:http/https
  3. apiserver 會協同 ETCD, kube-controller-manager, scheler 等組件准備下發新建容器的配置給到節點,協議:http/https
  4. apiserver 與 kubelet 進行交互,告知其容器創建的需求,協議:http/https;
  5. kubelet 與Docker等容器引擎進行交互,創建容器,協議:http/unix socket.
  6. 容器已然在集群節點上創建成功

攻擊apiserver

apiserver介紹:
在Kubernetes中,對於未鑒權對apiserver, 能訪問到 apiserver 一般情況下就能獲取了集群的許可權.

在攻擊者眼中Kubernetes APIServer

默認情況下apiserver都有鑒權:

未鑒權配置如下:

對於這類的未鑒權的設置來說,訪問到 apiserver 一般情況下就獲取了集群的許可權:

如何通過apiserver來進行滲透,可參考:https://Kubernetes.io/docs/reference/generated/kubectl/kubectl-commands

攻擊kubelet

每一個Node節點都有一個kubelet(每個節點上運行的代理)服務,kubelet監聽了10250,10248,10255等埠。

10250埠,是kubelet與apiserver進行通信對主要埠, 通過該埠,kubelet可以知道當前應該處理的任務.該埠在最新版Kubernetes是有鑒權的, 但在開啟了接受匿名請求的情況下,不帶鑒權信息的請求也可以使用10250提供的能力, 在Kubernetes早期,很多挖礦木馬基於該埠進行傳播.

在配置文件中,若進行如下配置,則可能存在未授權訪問漏洞.

/var/bin/kubulet/config/yaml

若10250埠存在未授權訪問漏洞,我們可以直接訪問/pods進行查看

根據在pods中獲取的信息,我們可以在容器中執行命令

curl -Gks https://host:10250/exec/{namespace}/{podname}/{containername} -d 'input=1' -d 'output=1' -d 'tty=1' -d 'command=whoami'

上述命令得到websocket地址,連接websocket得到命令結果:

使用wscat工具連接websocket

wscat -c 「https://X.X.X.X:10250/{websocket}」 --no-check

即可得到我們執行命令的結果.

獲取token

/var/run/secrets/kubernetes.io/serviceaccount

然後即可訪問kube-api server,獲取集群許可權

curl -ks -H "Authorization: Bearer ttps://master:6443/api/v1/namespaces/{namespace}/secrets

"

攻擊kubelet總體步驟如下:

攻擊dashboard

dashboard登陸鏈接如下:

http://xxx.xxx.xxx.xxx:xxxx/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login

dashboard界面如下:

dashboard是Kubernetes官方推出的控制Kubernetes的圖形化界面.在Kubernetes配置不當導致dashboard未授權訪問漏洞的情況下,通過dashboard我們可以控制整個集群。

默認情況下, dashboard是需要進行鑒權操作的,當用戶開啟了enable-skip-login時可以在登錄界面點擊Skip跳過登錄進入dashboard.

通過skip登陸的dashboard默認是沒有操作集群的許可權,因為Kubernetes使用RBAC(Role-based access control)機制進行身份認證和許可權管理,不同的serviceaccount擁有不同的集群許可權。

但有些開發者為了方便或者在測試環境中會為Kubernetes-dashboard綁定cluster-admin這個ClusterRole(cluster-admin擁有管理集群的最高許可權).

為Kubernetes-dashboard綁定cluster-admin 設置如下:

  1. 新建dashboard-admin.yaml內容
  2. apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: kubernetes-dashboardroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-adminsubjects : kind: ServiceAccount name: kubernetes-dashboard namespace: kubernetes-dashboard
  3. kubectl create -f dashboard-admin.yaml

後通過skip登陸dashboard便有了管理集群的許可權.

創建Pod控制node節點,該pod主要是將宿主機根目錄掛載到容器tmp目錄下。

新建一個Pod如下:

通過該容器的tmp目錄管理node節點的文件

攻擊etcd

Kubernetes默認使用了etcd v3來存儲數據, 若能na
etcd對內暴露2379埠,本地127.0.0.1可免認證訪問. 其他地址要帶—endpoint參數和cert進行認證。

未授權訪問流程:

攻擊docker remote api(Docker daemon公網暴露)

2375是docker遠程操控的默認埠,通過這個埠可以直接對遠程的docker 守護進程進行操作。Docker 守護進程默認監聽2375埠且未鑒權.

當機器以方式啟動daemon時,可以在外部機器對該機器的docker daemon進行直接操作:

docker daemon -H=0.0.0.0:2375

之後依次執行systemctl daemon-reload、systemctl restart docker

外部主機使用 即可操作暴露2375埠的主機.

-H

因此當你有訪問到目標Docker API 的網路能力或主機能力的時候,你就擁有了控制當前伺服器的能力。我們可以利用Docker API在遠程主機上創建一個特權容器,並且掛載主機根目錄到容器.

檢測目標是否存在docker api未授權訪問漏洞的方式也很簡單,訪問http://[host]:[port]/info路徑是否含有ContainersRunning、DockerRootDir等關鍵字。

攻擊kubectl proxy

二次開發所產生的問題

管理Kubernetes無論是使用 kubectl 或 Kubernetes dashboard 的UI功能,其實都是間接在和 APIServer 做交互.

如果有需求對k8s進行二次開發的話,大部分的開發功能請求了 APIServer 的 Rest API 從而使功能實現的。

例如:

類似於這樣去調用apiserver, 攻擊者若修改namespace、pod和容器名, 那麼即可造成越權.

推薦工具

Kube-Hunter掃描漏洞

kube-hunter是一款用於尋找Kubernetes集群中的安全漏洞掃描器

下載地址: https://github.com/aquasecurity/kube-hunter

CDK(強推)

CDK是一款為容器環境定製的滲透測試工具,在已攻陷的容器內部提供零依賴的常用命令及PoC/EXP。集成Docker/K8s場景特有的 逃逸、橫向移動、持久化利用方式,插件化管理。

下載地址: https://github.com/cdk-team/CDK/wiki/CDK-Home-CN

參考鏈接

https://developer.aliyun.com/article/765449?groupCode=aliyunsecurity
https://xz.aliyun.com/t/4276#toc-2
https://www.secrss.com/articles/29544
https://kubernetes.io/zh/docs/concepts/workloads/pods/#what-is-a-pod
https://www.huweihuang.com/kubernetes-notes/concepts/architecture/kubernetes-architecture.html
https://www.kubernetes.org.cn/service-account
https://www.aquasec.com/cloud-native-academy/cloud-native-applications/cloud-native-infrastructure/
https://www.cdxy.me/?p=827

⑽ kubernetes與docker的關系是什麼

合作關系,Docker作為單一的容器技術工具並不能很好地定義容器的「組織方式」和「管理規范」,難以獨立地支撐起生產級大規模容器化部署的要求。因此容器技術的發展就迅速走向了以Kubernetes為代表的「容器編排」的技術路線.

Kubernetes的出現也重新定義了微服務架構的技術方向,「雲原生」及「ServiceMesh(服務網格)」等概念,很大程度上也是依賴於Kubernetes所提供的基礎能力。




(10)重啟k8s的命令擴展閱讀:

常用命令分享

拉取docker鏡像

docker pull image_name

查看宿主機上的鏡像,Docker鏡像保存在/var/lib/docker目錄下:

docker images

刪除鏡像

docker rmi
docker.io/tomcat:7.0.77-jre7 或者 docker rmi b39c68b7af30

查看當前有哪些容器正在運行

docker ps

查看所有容器

docker ps -a

啟動、停止、重啟容器命令:

docker start container_name/container_iddocker stop container_name/container_iddocker restart container_name/container_id

後台啟動一個容器後,如果想進入到這個容器,可以使用attach命令:

docker attach container_name/container_id

刪除容器的命令:

docker rm container_name/container_id

查看當前系統Docker信息

docker info

閱讀全文

與重啟k8s的命令相關的資料

熱點內容
安卓機如何在電腦備份圖片 瀏覽:923
ca證書加密機價格 瀏覽:798
天乾地支年份演算法 瀏覽:796
程序員打造的視頻 瀏覽:6
java和php通信 瀏覽:680
為什麼黑程序員 瀏覽:162
程序員男生 瀏覽:455
戴爾文件夾內文件怎麼置頂 瀏覽:582
雲伺服器6m網速 瀏覽:722
vivo手機中國聯通伺服器地址 瀏覽:862
工程總控編譯失敗 瀏覽:706
燕趙紅楓app如何下載 瀏覽:867
php查殺軟體 瀏覽:878
教育管理學pdf 瀏覽:547
伺服器均衡怎麼使用 瀏覽:626
linux中jps 瀏覽:954
單片機實驗感想 瀏覽:561
程序員級別數學演算法邏輯 瀏覽:900
2k21公園怎麼換伺服器 瀏覽:724
php釋放資料庫連接 瀏覽:722