K8S安全學習之叢集搭建&基本概念理解
前言
最近在學習K8S相關雲原生技術,因為工作中正好接觸到,便一直想找個機會深入學習一下這個方向的利用與防禦,學習之後發現東西挺多。由於篇幅原因,決定將其整理成一個系列,拆分成幾篇文章輸出,本篇文章主要介紹K8s的搭建和概念的介紹,在理解概念之後,會逐步分享k8s中的攻擊和防禦措施。本系列文章主要為個人學習記錄總結,若有錯誤,煩請斧正。
什麼是Kubernetes?
隨著微服務架構被越來越多的公司使用,大部分單體應用正逐步被拆解成小的、獨立執行的微服務。微服務的優勢這裡不做探討,但是其帶來的服務維護問題大大增加,若想要在管理大量微服務的情況下還需要讓資源利用率更多且硬體成本相對更低,那麼基於容器部署的微服務的一些自動化設施的需求就這樣誕生了,於是就有了Kubernetes(簡稱k8s),其提供的特性有:
服務發現和負載均衡
儲存編排
自動釋出和回滾
自愈
金鑰及配置管理
透過下面架構圖可以看到其有上下兩部分對應的
Master&Node
節點構成,這兩種角色分別對應著控制節點和計算節點。
Master控制節點主要出發點在於如何編排、管理、排程使用者提交的作業,一個k8s叢集中至少要有一臺master節點。
Kubernetes控制節點主要由以下幾個核心元件組成:
etcd : 儲存了整個叢集的狀態,它是一個高可用性鍵值儲存,可以在多個節點之間分佈。只有Kubernetes API伺服器可以訪問它,因為它可能具有一些敏感資訊。這是一個分散式鍵值儲存,所有人都可以訪問。簡而言之:儲存節點資訊
apiserver提供了資源操作的唯一入口,並提供認證、授權、訪問控制、API註冊和發現等機制,是讀取與解析請求指令的中樞。
controller manager負責維護叢集的狀態,比如故障檢測、自動擴充套件、滾動更新等,簡而言之即維護k8s資源。
scheduler負責資源的排程,按照預定的排程策略將Pod排程到相應的機器上,即:負載均衡排程器。
對於計算節點:
kubelet 存在於每個node節點上,負責維護容器的生命週期,同時也負責Volume(CSI)和網路(CNI)的管理。
Container runtime負責映象管理以及Pod和容器的真正執行(CRI)
kube-proxy負責為Service提供cluster內部的服務發現和負載均衡
K8s搭建
單機安裝
關於單機安裝
k8s
,我使用的相關環境如下:
- macOS:Catalina 10.15.1
- Docker Desktop Vesion:3.0.2
- Kubernetes:1.19.3
由於映象的下載涉及到網路原因,因此這裡使用了開源專案
來解決這個問題,需要注意的是要修改
images
的相關映象的版本,要和此時
Kubernetes
配對上才行,比如我設定的是:
k8s.gcr.io/kube-proxy:v1.19.3=gotok8s/kube-proxy:v1.19.3 k8s.gcr.io/kube-controller-manager:v1.19.3=gotok8s/kube-controller-manager:v1.19.3 k8s.gcr.io/kube-scheduler:v1.19.3=gotok8s/kube-scheduler:v1.19.3 k8s.gcr.io/kube-apiserver:v1.19.3=gotok8s/kube-apiserver:v1.19.3 k8s.gcr.io/coredns:1.7.0=gotok8s/coredns:1.7.0 k8s.gcr.io/pause:3.2=gotok8s/pause:3.2 k8s.gcr.io/etcd:3.4.13-0=gotok8s/etcd:3.4.13-0
隨後開啟
Docker
,進入設定介面,勾選
Enable Kubernetes
即可:
不出意外,介面左下角會出現
Kubernetes running
的提示,這樣就安裝成功了。
如果狀態一直處於
Kubernetes starting
狀態,可在終端執行以下命令然後重啟
Docker
:
rm -rf ~/.kube rm -rf ~/Library/Group\\ Containers/group.com.docker/pki/
K8叢集搭建
準備
準備三臺機器:
10.206.32.6(2核4G):Master:
執行:
hostnamectl set-hostname master
echo "127.0.0.1 $(hostname)" >> /etc/hosts
10.206.32.9(2核2G):Node01
執行:
hostnamectl set-hostname node01
echo "127.0.0.1 $(hostname)" >> /etc/hosts
110.206.32.13(2核2G):Node02
執行:
hostnamectl set-hostname node02
echo "127.0.0.1 $(hostname)" >> /etc/hosts
Kubernetes版本:v1.19.3
Docker版本:19.03.12
開始前請檢查以下事項:
CentOS 版本:>= 7.6
CPU:>=2
IP:互通
關閉 swap:
swapoff -a
關閉防火牆:systemctl stop firewalld
將橋接的IPV4流量傳遞到iptables 的鏈:
cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system
- 安裝docker環境
配置國內kubernetes源:
cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes Repo
baseurl=
gpgcheck=0
enabled=1
EOF
安裝相關依賴工具:
# 安裝kubelet 1.19.3 yum install -y kubelet-1.19.3 kubeadm-1.19.3 kubectl-1.19.3 #在交換分割槽的可以設定忽略禁止使用Swap的限制,不然無法啟動Kubelet view /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS="--fail-swap-on=false" # 設定開機啟動 systemctl enable kubelet.service && systemctl start kubelet.service # 檢視狀態 systemctl status kubelet.service
初始化Master
在主節點(10.206.32.6)執行以下命令:
export MASTER_IP=10.206.32.6 export APISERVER_NAME=apiserver.demo export POD_SUBNET=10.100.0.1/16 echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
新建指令碼
init_master.sh
vim init_master.sh
#!/bin/bash # 只在 master 節點執行 # 指令碼出錯時終止執行 set -e if [ ${#POD_SUBNET} -eq 0 ] || [ ${#APISERVER_NAME} -eq 0 ]; then echo -e "\033[31;1m請確保您已經設定了環境變數 POD_SUBNET 和 APISERVER_NAME \033[0m" echo 當前POD_SUBNET=$POD_SUBNET echo 當前APISERVER_NAME=$APISERVER_NAME exit 1 fi # 檢視完整配置選項 rm -f ./kubeadm-config.yaml cat <<EOF > ./kubeadm-config.yaml apiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterConfiguration # k8s 版本 kubernetesVersion: v1.19.3 imageRepository: registry.aliyuncs.com/k8sxio controlPlaneEndpoint: "${APISERVER_NAME}:6443" networking: serviceSubnet: "10.96.0.0/16" podSubnet: "${POD_SUBNET}" dnsDomain: "cluster.local" EOF # kubeadm init # 根據您伺服器網速的情況,您需要等候 3 - 10 分鐘 kubeadm config images pull --config=kubeadm-config.yaml kubeadm init --config=kubeadm-config.yaml --upload-certs # 配置 kubectl rm -rf /root/.kube/ mkdir /root/.kube/ cp -i /etc/kubernetes/admin.conf /root/.kube/config # 安裝 calico 網路外掛 # 參考文件 echo "安裝calico-3.13.1" rm -f calico-3.13.1.yaml wget kubectl apply -f calico-3.13.1.yaml
如果出錯:
# issue 01 # [ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1 # 所有機器執行 echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables
檢查
master
初始化結果:
# 直到所有的容器組處於 Running 狀態 watch kubectl get pod -n kube-system -o wide # 檢視 master 節點初始化結果 kubectl get nodes -o wide
如下圖:
獲得join命令引數
直接在
master
執行:
kubeadm token create --print-join-command
比如此時輸出:
# 有效期兩小時 kubeadm join apiserver.demo:6443 --token uysznt.3enu78oflli383zt --discovery-token-ca-cert-hash sha256:345664bfbdfd9178ea69edf2469387d7d224121b208bb90bad5a2c1952bcb9f3
初始化Node
在所有
node
執行:
export MASTER_IP=10.206.32.6 export APISERVER_NAME=apiserver.demo echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts # 替換為 master 節點上 kubeadm token create 命令的輸出 kubeadm join apiserver.demo:6443 --token vh5hl9.9fccw1mzfsmsp4gh --discovery-token-ca-cert-hash sha256:6970397fdc6de5020df76de950c9df96349ca119f127551d109430c114b06f40
檢查初始化結果
在
master
節點執行:
kubectl get nodes -o wide
輸出結果如下:
Kubernetes Dashboard
可以將容器化應用程式部署到
Kubernetes
叢集,對容器化應用程式進行故障排除,以及管理叢集資源。
安裝
安裝命令如下:
wget < kubectl apply -f recommended.yaml kubectl get pods --namespace=kubernetes-dashboard -o wide
此處執行完會發現
STATUS
都是
ContainerCreating,
kubectl describe pod dashboard-metrics-scraper-856586f554-tkm49 --namespace=kubernetes-dashboard
檢視日誌找找原因,發現是因為
metrics-scraper:v1.0.6
映象下載不下來,手動執行:
docker pull kubernetesui/metrics-scraper:v1.0.1
拉下來之後就妥了。
最後我們需要將訪問形式改為
NodePort
訪問:
kubectl --namespace=kubernetes-dashboard edit service kubernetes-dashboard # 將裡面的 type: ClusterIP 改為 type: NodePort
儲存後,執行:
kubectl --namespace=kubernetes-dashboard get service kubernetes-dashboard
終端輸出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes-dashboard NodePort 10.98.194.124 <none> 443:31213/TCP 107m
Token
在瀏覽器訪問:
:
看介面需要生成
Token
:
vim admin-user.yaml
# 輸入 apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard # 儲存退出 vim admin-user-role-binding.yaml # 輸入 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard # 儲存退出
# 執行命令載入配置 kubectl create -f admin-user.yaml kubectl create -f admin-user-role-binding.yaml # 若出現已存在 # 執行:kubectl delete -f xxx.yaml 即可
獲取令牌:
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
複製
token
到剛才的介面登入即可,登入後介面如下:
如果想延長
Token
的有效時間:
然後在
containners->args
加上
--token-ttl=43200
。
部署映象
下拉一個你自己想部署的映象,具體命令如下(主節點執行):
# 部署 kubectl run hello --image=xxx/hello --port=5000 # 列出 pod kubectl get pods # 建立一個服務物件 # NodePort 在所有節點(虛擬機器)上開放一個特定埠,任何傳送到該埠的流量都被轉發到對應服務 kubectl expose po hello --port=5000 --target-port=5000 --type=NodePort --name hello-http # 列出服務 kubectl get services
概念理解
俗話說,磨刀不誤砍柴工。上面我們成功搭建了k8s叢集,接下來我們主要花時間瞭解一下k8s的相關概念,為後續掌握更高階的知識提前做好準備。
本文主要講解以下四個概念:
Pod
Deployment
Service
Namespace
Deployment
讓我們從使用
Deployment
執行一個無狀態應用來開始吧,比如執行一個
nginx Deployment
(建立檔案:
nginx-deployment.yaml
):
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80
配置檔案第二行,有個
kind
欄位,表示的是此時
yaml
配置的型別,即
Deployment
。什麼是
Deployment
?這裡我先不做解釋,讓我們先實踐,看能不能在使用過程中體會出這個型別的概念意義。
在終端執行:
kubectl apply -f ./nginx-deployment.yaml # 輸出 deployment.apps/nginx-deployment created
然後透過以下命令分別檢視叢集中建立的 Deployment 和 Pod 的狀態:
# 檢視 Deployment kubectl get deployments # 輸出 NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 1/1 1 1 27m # 檢視 Pod kubectl get pods # 輸出 NAME READY STATUS RESTARTS AGE nginx-deployment-585449566-cl6rv 1/1 Running 0 27m # 檢視 Deployment 的資訊 kubectl describe deployment nginx # 刪除 Deployment kubectl delete deployment nginx-deployment # 檢視 Pod 的資訊 # kubectl describe pod <pod-name> # 這裡的 <pod-name> 是某一 Pod 的名稱 kubectl describe pod nginx-deployment-585449566-cl6rv # 進入容器 kubectl exec -it nnginx-deployment-585449566-cl6rv -- /bin/bash
此時我們已經成功在k8s上部署了一個例項的nginx應用程式。k8s中的應用程式是透過 Deployment來部署的,Deployment來指導k8s完成應用程式的部署和更新維護。比如說,當Deployment在部署應用時,master節點會選擇最合適的節點建立包含相應Container(容器)的POD
又比如說,Deployment會監控應用程式例項,當執行應用程式的工作節點當機時,它將會在判斷叢集中最適宜重新部署的工作節點,並在其上面重新建立新的例項(新建立的應用程式的POD ip和pod名會與之前的不同)。
但是,等等!我們好像又看到了一個新的名詞
Pod
,這又是什麼?讓我們帶著疑問繼續往下看吧。
Pod
在Kubernetes中,最小的管理元素不是一個個獨立的容器,而是pod(目的在於解決容器間緊密協作關係的難題)
Pod
是一組並置的容器,代表了
Kubernetes
中的基本構建模組:
-
一個
Pod
包含:
一個或多個容器(container)
容器(container)的一些共享資源:儲存、網路等
-
一個
Pod
的所有容器都執行在同一個節點
容器可以被管理,但是容器裡面的多個程式實際上是不好被管理的,所以 容器被設計為每個容器只執行一個程式。
容器的本質實際上就是一個程式,
Namespace 做隔離,Cgroups 做限制,rootfs 做檔案系統。在一個容器只能執行一個程式的前提下,實際開發過程中一個應用是由多個容器緊密協作才可以成功地執行起來。因此,我們需要另一種更高階的結構來將容器繫結在一起,並將它們作為一個單元進行管理,這就是
Pod
出現的目的。
如何定義並建立一個Pod
建立檔案
nginx-pod.yaml
:
apiVersion: v1 kind: Pod metadata: name: nginx labels: name: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80
相關欄位解釋如下:
kind: 該配置的型別,這裡是 Pod
metadata:後設資料
- name:Pod的名稱
- labels:標籤
spec:期望Pod實現的功能
containers:容器相關配置
name:container名稱
image:映象
ports:容器埠
containerPort:應用監聽的埠
執行:
# 建立 kubectl create -f nginx-pod.yaml # 輸出 pod/nginx created # 檢視 kubectl get pods # 輸出 NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 10s nginx-deployment-585449566-cl6rv 1/1 Running 0 33m # 檢視 Pod 完整的描述性檔案 # yaml 是你想看的格式 也可以是 json kubectl get po nginx -o yaml # 刪除 Pod kubectl delete -f nginx-pod.yaml
這裡簡單介紹了用宣告式API怎麼建立
Pod
,但從技術角度看,
Pod
又是怎樣被建立的呢?實際上
Pod
只是一個邏輯概念,
Pod
裡的所有容器,共享的是同一個
Network Namespace
,並且可以宣告共享同一個
Volume
。
Pod
除了啟動你定義的容器,還會啟動一個
Infra
容器,這個容器使用的就是
k8s.gcr.io/pause
映象,它的作用就是整一個
Network Namespace
方便使用者容器加入,這就意味著
Pod
有以下特性:
內部直接使用
127.0.0.1
通訊,網路裝置一致(Infra
容器決定)只有一個IP地址
Pod
的生命週期只跟Infra
容器一致,而與使用者容器無關
label
現在我們的叢集裡面只執行了一個
Pod
,但在實際環境中,我們執行數十上百個
Pod
也是一件很正常的事情,這樣就引出了
Pod
管理上的問題,我們可以透過標籤來組織
Pod
和所有其他
Kubernetes
物件。
前面
nginx-pod.yaml
裡面就宣告瞭
labels
欄位,標籤為
name
,相關操作記錄如下:
`# 檢視標籤 kubectl get pods --show-labels # 輸出 NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 10m name=nginx nginx-deployment-585449566-cl6rv 1/1 Running 0 43m app=nginx,pod-template-hash=585449566 # 增加標籤 kubectl label pods nginx version=latest # 輸出 pod/nginx labeled # 檢視特定標籤 kubectl get pods -l "version=latest" --show-labels # 更新標籤 kubectl label pods nginx version=1 --overwrite # 刪除標籤 kubectl label pods nginx version-
Namespace
利用標籤,我們可以將
Pod
和其他物件組織成一個組,這是最小粒度的分類,當我們需要將物件分割成完全獨立且不重疊的組時,比如我想單獨基於
k8s
搭建一套
Flink
叢集,我不用想讓我的
Flink
和前面搭建的
Nginx
放在一起,這個時候,名稱空間(namespace)的作用就體現出來了。
# 列出所有的名稱空間 kubectl get ns # 輸出,我們目前都是在 default 名稱空間中進行操作 NAME STATUS AGE default Active 124m kube-node-lease Active 124m kube-public Active 124m kube-system Active 124m kubernetes-dashboard Active 37m local-path-storage Active 124m
讓我們建立一個名稱空間
vim cus-ns.yaml
,輸入:
apiVersion: v1 kind: Namespace metadata: name: cus-ns
讓我們在終端實踐一番:
# 開始建立名稱空間 kubectl create -f cus-ns.yaml # 輸出 namespace/cus-ns created # 為新建資源選擇名稱空間 kubectl create -f nginx-pod.yaml -n cus-ns #輸出 pod/nginx created
這裡我們可以暫時先做一個總結,如前面所說,
Pod
可以表示
k8s
中的基本部署單元。經過前面的講解,你應該知道以下一些知識點:
手動增刪改查
Pod
讓其服務化(
Service
)
但是在實際使用中,我們並不會直接人工干預來管理
Pod
,為什麼呢?當
Pod
健康出問題或者需要進行更新等操作時,人是沒有精力來做這種維護管理工作的,但我們擅長創造工具來自動化這些繁瑣的事情,所以我們可以使用後面介紹的
Deployment
。
外部訪問
此時我們已經啟動了一個
nginx
,我們有哪些方法可以對
Pod
進行連線測試呢?
可以使用如下命令:
kubectl port-forward nginx 8088:80 # 輸出 Forwarding from 127.0.0.1:8088 -> 80 Forwarding from [::1]:8088 -> 80 # 再開一個終端訪問測試或者開啟瀏覽器 curl <
顯然,成功訪問,但是這個有個問題就是此埠不會長期開放,一旦一定時間內沒有訪問,就會自動斷掉,我們需要其他的方式來進行訪問,比如後面會提到的
Service
,這裡就簡單執行個命令,大家感受一下:
# 建立一個服務物件 # NodePort 在所有節點(虛擬機器)上開放一個特定埠,任何傳送到該埠的流量都被轉發到對應服務 kubectl expose po nginx --port=80 --target-port=80 --type=NodePort --name nginx-http # 輸出 service/nginx-http exposed # 檢視服務 kubectl get svc # 輸出 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 130m nginx-http NodePort 10.96.114.244 <none> 80:30236/TCP 21s # 終端訪問測試 curl < # 輸出 html, 表示成功埠成功開放給外部
Service
Service 服務的主要作用就是替代 Pod 對外暴露一個不變的訪問地址
在本文中
Pod
部分的
外部訪問
小節,就已經提到並演示了
Service
,它很方便地將我們的服務埠成功開放給外部訪問。
介紹
我們的
Pod
是有生命週期的,它們可以被建立、銷燬,但是一旦被銷燬,這個物件的相關痕跡就沒有了,哪怕我們用
ReplicaSet
讓他又復生了,但是新
Pod
的
IP
我們是沒法管控的。
很顯然,如果我們的後端服務的介面地址總是在變,我們的前端人員心中定然大罵,怎麼辦?這就輪到
Service
出場了。
定義 Service
前面我們建立了一個名為
nginx-http
的
Services
,用的是命令列;接下來我們介紹一下配置檔案的形式,在
nginx-deployment.yaml
後面增加以下配置:
--- kind: Service apiVersion: v1 metadata: name: nginx spec: selector: app: nginx type: NodePort ports: - nodePort: 30068 port: 8068 protocol: TCP targetPort: 80
相信上述配置,大部分的欄位看起來都沒什麼問題了吧,先說一下埠這塊的含義:
nodePort:透過任意節點的
30068
埠來訪問Service
port:叢集內的其他容器組可透過
8068
埠訪問Service
targetPort:
Pod
內容器的開發埠
這裡我想強調的是
type
欄位,說明如下:
ClusterIP:預設型別,服務只能夠在叢集內部可以訪問
NodePort:透過每個 Node 上的 IP 和靜態埠(
NodePort
)暴露服務LoadBalancer:使用雲提供商的負載均衡器,可以向外部暴露服務。
關於
LoadBalancer
,基本上是雲商會提供此型別,如果是我們自行搭建的,就沒有此型別可選,但是很多開源專案預設是啟用這種型別,我們可以自行打一個補丁來解決這個問題:
kubectl patch svc {your-svc-name} -n default -p '{"spec": {"type": "LoadBalancer", "externalIPs":["0.0.0.0"]}}'
執行生效命令:
kubectl apply -f ./nginx-deployment.yaml # 輸出 deployment.apps/nginx-deployment unchanged service/nginx created # 檢視服務 kubectl get services -o wide # 輸出 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 134m <none> nginx-http NodePort 10.96.114.244 <none> 80:30236/TCP 4m41s name=nginx,version=latest # 終端測試 curl <
除了前面提的兩種方法(
NodePort
、
LoadBalancer
),還有另外一種方法——
Ingress
資源。我們為什麼需要引入
Ingress
,最主要的原因是
LoadBalancer
需要公有的IP地址,自行搭建的就不要考慮了。
而
Ingress
非常強大,它位於多個服務之前,充當叢集中的
智慧路由器或入口點:
窺一斑而知全豹,好好了解完
Pod
之後,再繼續瞭解
k8s
的概念也就水到渠成了。我們一般不會直接建立
Pod
,畢竟透過建立
Deployment
資源可以很方便的建立管理
Pod
(水平擴充套件、伸縮),並支援宣告式地更新應用程式。
我們一開始就是以
Deployment
舉例,當時啟動配置檔案我們看到了一個
Deployment
資源和一個
Pod
,檢視命令如下:
kubectl get deployments # 輸出 NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 0/1 1 0 4s kubectl get pods # 輸出 如果名字有變化不用在意,只是我重新建立了一個 Deployment NAME READY STATUS RESTARTS AGE nginx-deployment-585449566-mnrtn 1/1 Running 0 2m1s
這裡我們再增加一條命令:
kubectl get replicasets.apps # 輸出 NAME DESIRED CURRENT READY AGE nginx-deployment-585449566 1 1 1 10m
嗯嗯~,讓我們捋一捋,當我們建立一個
Deployment
物件時,
k8s
不會只建立一個
Deployment
資源,還會建立另外的
ReplicaSet
以及1個
Pod
物件。所以問題來了,
ReplicaSet
又是個是什麼東西?
ReplicaSet
如果你更新了
Deployment
的
Pod
模板,那麼
Deployment
就需要透過滾動更新(rolling update)的方式進行更新。
而滾動更新,離不開
ReplicaSet
,說到
ReplicaSet
就得說到
ReplicationController
(棄用)。
ReplicationController是一種k8s資源,其會持續監控正在執行的pod列表,從而保證Pod的穩定(在現有Pod丟失時啟動一個新Pod),也能輕鬆實現Pod的水平伸縮
ReplicaSet
的行為與
ReplicationController
完全相同,但
Pod
選擇器的表達能力更強(允許匹配缺少某個標籤的Pod,或包含特定標籤名的Pod)。所以我們可以將
Deployment
當成一種更高階的資源,用於部署應用程式,並以宣告的方式管理應用,而不是透過
ReplicaSet
進行部署,上述命令的建立關係如下圖:
如上圖,
Deployment
的控制器,實際上控制的是
ReplicaSet
的數目,以及每個
ReplicaSet
的屬性。我們可以說
Deployment
是一個兩層控制器:
Deployment–>ReplicaSet–>Pod
這種形式下滾動更新是極好的,但這裡有個前提條件那就是
Pod
是無狀態的,如果執行的容器必須依賴此時的相關執行資料,那麼回滾後這些存在於容器的資料或者一些相關執行狀態值就不存在了,對於這種情況,該怎麼辦?此時需要的就是
StatefulSet
(部署有狀態的多副本應用)。
StatefulSet
如果透過
ReplicaSet
建立多個
Pod
副本(其中描述了關聯到特定持久卷宣告的資料卷),那麼這些副本都將共享這個持久卷宣告的資料卷。
那如何執行一個pod的多個副本,讓每個pod都有獨立的儲存卷呢?對於這個問題,之前學習的相關知識都不能提供比較好的解決方案。
k8s
提供了
Statefulset
資源來執行這類Pod,它是專門定製的一類應用,這類應用中每一個例項都是不可替代的個體,都擁有穩定的名字和狀態。
對於有狀態的應用(例項之間有不對等的關係或者依賴外部資料),主要需要對以下兩種型別的狀態進行復刻:
儲存狀態:應用的多個例項分別繫結了不同的儲存資料,也就是讓每個Pod都有自己獨立的儲存卷
拓撲狀態:應用的多個例項之間不是完全對等的關係,各個Pod需要按照一定的順序啟動
來自 “ freebuf ”, 原文作者:Pamela@塗鴉智慧安全實驗室;原文連結:https://www.freebuf.com/articles/container/324421.html,如有侵權,請聯絡管理員刪除。
相關文章
- Kafka學習之(五)搭建kafka叢集之Zookeeper叢集搭建Kafka
- Kafka學習之(六)搭建kafka叢集Kafka
- Redis學習之 Redis3.0.x 叢集搭建RedisS3
- mysql學習筆記之快速搭建PXC叢集(Mycat分片)MySql筆記
- ZooKeeper學習筆記一:叢集搭建筆記
- 教你如何搭建K8S叢集。K8S
- k8s——搭建叢集環境K8S
- Linux學習之使用RHCS套件搭建HA高可用叢集Linux套件
- k8s之叢集管理K8S
- Nginx學習筆記(反向代理&搭建叢集)Nginx筆記
- 在K8S上搭建Redis叢集K8SRedis
- Kubeadm方式搭建K8S叢集K8S
- k8s叢集搭建--kubeadm方式K8S
- Docker 與 K8S學習筆記(二十三)—— Kubernetes叢集搭建DockerK8S筆記
- rocketMq之叢集搭建(三)MQ
- 學習叢集。
- Mac + Docker + K8S 本地搭建K8S叢集MacDockerK8S
- 簡單的方式搭建k8s叢集K8S
- 高階k8s HA 叢集搭建(一)K8S
- 使用kind快速搭建本地k8s叢集K8S
- 從零搭建K8S測試叢集K8S
- 2019最新k8s叢集搭建教程 (centos k8s 搭建)K8SCentOS
- 教你用multipass快速搭建k8s叢集K8S
- k8s搭建叢集軟硬體配置要求K8S
- Rancher 下圖形介面 搭建 K8S 叢集K8S
- 欠你們的 → k8s 叢集搭建,除夕奉上!K8S
- k8s介紹及與docker搭建叢集K8SDocker
- 搭建zookeeper叢集(偽叢集)
- mongodb叢集搭建及配置安全認證MongoDB
- 叢集搭建
- 大資料之CDH叢集搭建大資料
- redis學習-10(叢集)Redis
- 純手工搭建k8s叢集-(2)核心模組部署K8S
- zookeeper叢集及kafka叢集搭建Kafka
- 基於kerberos的hadoop安全叢集搭建ROSHadoop
- 微服務Consul系列之叢集搭建微服務
- Redis系列:搭建Redis叢集(叢集模式)Redis模式
- 從零開始搭建高可用的k8s叢集K8S