Kubernetes安裝部署基礎簡介

kubernetes,也叫k8s,是一個用于自動化部署、擴展、管理容器化應用的開源系統。

基礎概念

  • Cluster

Kubernetes將集群分為一個Master和一些Node。
Master上運行著集群相關的一組進程kube-apiserver 、 kube-controller-manager和kube-scheduler,這些進程實現了整個集群的資源管理、Pod調度、彈性伸縮、安全控制、系統監控和糾錯等管理功能,并且都是自動完成的。
Node作為集群中的工作節點,運行真正的應用程序,在Node上Kubernetes管理的最小運行單元是Pod。在Node上運行著Kubernetes的kubelet、kube-proxy服務進程,這些服務進程負責Pod的創建、啟動、監控、重啟、銷毀,以及實現軟件模式的負載均衡器。


集群結構
  • Pod

Pod運行在Node上,Node既可以是物理機也可以是虛擬機,通常一個Node上可以運行多個上百個Pod。每個Pod包含一個Pause容器和多個業務容器,業務容器共用Pause Container的網絡棧和Volume掛載卷。通常將一組密切相關的業務放在一個Pod上。
Pod是Kubernetes調度的最小單位,同一Pod中的容器始終被一起調用。
并不是每個Pod和它內部運行的容器都能映射到一個Service上,只有提供服務的Pod才會被映射為一個Service。


單個Pod結構
  • Service

個人理解Service就是管理一組Pod的網絡訪問。它有如下特點
擁有唯一指定的名稱、擁有一個虛擬IP、提供遠程服務能力、被映射到提供這種服務能力的一組容器應用上(也就是一組提供服務的Pod對應一個Service)。
Service一旦創建就不會再變化。
為了建立Service和Pod之間的關系,Kubernetes首先給每個Pod貼上一個標簽,然后給相應的Service定義標簽選擇器(Label Selector),比如標簽選擇器的選擇條件是name=mysql,意味著該Service要作用于所有包含name=mysql 標簽的Pod。


Service和Pod的映射關系
  • RC(Replication Controller)

RC控制Pod的運行。
在Kubernetes中為服務器擴容,只需為需要擴容的Service關聯的Pod創建一個RC。在一個RC文件中包含以下關鍵信息:

  • 目標Pod定義
  • 目標Pod需要運行的副本數量
  • 要監控的Pod標簽

創建好RC后,K8s通過RC中標簽篩選出對應的Pod實例,并實時監控其狀態和數量。如果實例數量少于定義的副本數量,則會根據在RC中定義的Pod模板創建一個新的Pod,然后將此Pod調度到合適的Node上啟動運行,直到Pod實例的數量達到預定目標。這個過程完全是自動化的,無須人工干預。后續的服務升級也將通過修改RC來自動完成。

Kubernetes安裝

操作系統:CentOS Linux release 7.5.1804 (Core)
Docker版本:19.03.11
Kubernetes版本:

2.1 運行時(Container runtimes)

需要在每個Node上安裝運行時保證Pod可以運行,Kubernetes常用的運行時有:containerd、CPI-O、Docker。本例采用Docker。

安裝Docker
#1. 設置倉庫,安裝需要的包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
#2. 添加Docker倉庫
sudo yum-config-manager --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo
#3. 安裝Docker CE
sudo yum update -y && sudo yum install -y \
  containerd.io-1.2.13 \
  docker-ce-19.03.11 \
  docker-ce-cli-19.03.11
#4. 創建/etc/docker
sudo mkdir /etc/docker
#5. 設置Docker deamon
cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
EOF
#6. sudo mkdir -p /etc/systemd/system/docker.service.d
7. 重啟Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
#8. 添加至開機啟動
sudo systemctl enable docker

2.2 使用kubeadm引導集群

2.2.1 安裝kubeadm,kubelet,kubectl
  • kubeadm 引導集群的命令
  • kubelet 在集群中所有計算機上運行的組件,它執行諸如啟動Pod和容器之類的操作。
  • kubectl 與集群通信的命令行工具。
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

# Set SELinux in permissive mode (effectively disabling it)允許容器訪問主機文件
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

sudo systemctl enable --now kubelet

現在kubelet每隔幾秒就啟動一次,因為它在一個crashloop中等待kubeadm的指令。
在使用Docker時,Kubeadm將自動監測kubelet的cgroup驅動程序,并在運行時將它設置到/var/lib/kubelet/config.yaml文件

2.2.2 kubeadm config

注意:配置文件仍然被認為是測試版,在未來的版本中可能會改變。

Kubeadm提供了配置文件用于復雜定制,同時kubeadm將配置文件以ConfigMap的形式保存到集群之中,便于后續的查詢和升級工作。
kubeadm config子命令提供了對這一組功能的支持。

  1. kubeadm config upload from-file:由配置文件上傳到集群中生成ConfigMap。
  2. kubeadm config upload from-flags:由配置參數生成ConfigMap。
  3. kubeadm config print init-defaults:輸出kubeadm init默認參數文件的內容。
  4. kubeadm config print join-defaults:輸出kubeadm join默認參數文件的內容。
  5. kubeadm config migrate:在新舊版本之間進行配置轉換。
  6. kubeadm config images list:列出所需的鏡像列表。
  7. kubeadm config images pull:拉取鏡像到本地。
#用默認配置生成文件
[root@test-38 ~]# kubeadm config print init-defaults > init.default.yaml
2.2.3 運行kubeadm init 安裝Master
  • 關閉Swap
swapoff -a
sed -i 's/.*swap.*/#&/' /etc/fstab
cat /etc/fstab
  • 運行Kubeadm init
kubeadm init
//也可自定義kubeadm config ,本例采用默認配置

等待一段時間后,Kubernetes安裝Master成功,顯示如下成功信息,成功信息包含了加入節點的指令和所需要的token(kubeadm join)


Master安裝成功

按照信息提示執行命令,復制配置文件到普通用戶的home目錄下:

[root@test-38 lib]# mkdir -p $HOME/.kube
[root@test-38 lib]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@test-38 lib]# chown $(id -u):$(id -g) $HOME/.kube/config
[root@test-38 lib]# 

這樣就在Master上安裝了Kubernetes,但在集群內還沒有可用的工作Node,并缺乏對容器的網絡配置。
此時可以驗證2.2.2提到的configMap

[root@test-38 ~]# kubectl get -n kube-system configmap
NAME                                 DATA   AGE
coredns                              1      99m
extension-apiserver-authentication   6      99m
kube-proxy                           2      99m
kube-root-ca.crt                     1      99m
kubeadm-config                       2      99m
kubelet-config-1.20                  1      99m

可以看到其中生成了kubeadm-config的ConfigMap對象

2.2.4安裝Node,加入集群

對于新節點的添加,系統準備和kubernetes yum源的配置是一樣的

kubeadm join 192.168.1.38:6443 --token qfp9bn.47raj0gk26ug6jlq     --discovery-token-ca-cert-hash sha256:ae84e70d9559f21ad42e7d9559706f597654531000ad218d0afa9ed6af83e83a 

kubeadm在Master上也安裝了kubelet,在默認情況下并不參與工作負載。如果希望安裝一個單機環境,可以執行下面的命令:

[root@test-38 ~]# kubectl taint nodes --all node-role.kubernetes.io/master-
node/test-38 untainted

這將從任何擁有 node-role.kubernetes.io/master taint 標記的節點中移除該標記, 包括控制平面節點,這意味著調度程序將能夠在任何地方調度 Pods。

2.2.5 安裝網絡插件

執行kubectl get nodes,會發現Master處于NotReady的狀態,這是因為還沒有安裝CNI網絡插件:

[root@test-38 ~]# kubectl get nodes
NAME      STATUS     ROLES                  AGE   VERSION
test-38   NotReady   control-plane,master   24m   v1.20.4

安裝CNI網絡插件,這里選擇的是weave

kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
2.2.6 驗證kubernetes集群是否安裝完成
kubectl get pods --all-namespaces

如果發現有狀態錯誤的Pod,則可以執行kubectl --namespace=kube-systemdescribe pod<pod_name>來查看錯誤原因,常見的錯誤原因是鏡像沒有下載完成。

2.2.7 部署應用

使用 kubernetes create deployment部署應用:

kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

部署應用做了以下兩件事:

  • 尋找合適的可以運行應用實例的Node
  • 安排應用程序在該節點上運行
  • 配置集群以在需要時在新節點上重新安排實例
    查看deployment
[root@test-38 ~]# kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           103m

2.2.8 訪問應用

默認情況下,所有Pod只能在集群內部訪問,當使用kubectl時,我們正在通過API端點進行交互來和我們的程序進行通信。

  1. 通過代理訪問API

kubectl可以創建一個代理,該代理會將通信轉發到集群范圍的專用網絡

[root@test-38 ~]# kubectl proxy
Starting to serve on 127.0.0.1:8001

現在我們有了一個我們主機和kubernetes集群的連接,這個代理允許我們通過API進行訪問。

[root@test-38 ~]# curl http://localhost:8001/version
{
  "major": "1",
  "minor": "20",
  "gitVersion": "v1.20.4",
  "gitCommit": "e87da0bd6e03ec3fea7933c432i63d151aafdusj",
  "gitTreeState": "clean",
  "buildDate": "2021-02-18T16:03:00Z",
  "goVersion": "go1.15.8",
  "compiler": "gc",
  "platform": "linux/amd64"
}

API 服務器將基于Pod名稱自動為每個Pod創建一個端點,該端點也可以通過代理進行訪問。
首先我們要現獲取Pod名稱,然后將名稱存儲在環境變量POD_NAME:

[root@test-38 ~]# export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
[root@test-38 ~]# echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-57978f5f5d-jcn7k

使用kubectl logs $POD_NAME查看pod日志

[root@test-38 ~]# kubectl logs  kubernetes-bootcamp-57978f5f5d-jcn7k
Kubernetes Bootcamp App Started At: 2021-03-01T08:07:32.804Z | Running On:  kubernetes-bootcamp-57978f5f5d-jcn7k 

還可以在container內部執行命令,具體可以參考https://kubernetes.io/docs/tutorials/kubernetes-basics/explore/explore-interactive/

  1. 從外部訪問應用
    查看現有的service可以看到,系統有一個默認創建的service。
[root@test-38 ~]# kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   2d17h

要訪問應用只能訪問容器的8080端口,我們要將容器的8080端口映射到節點的端口。

[root@test-38 ~]# kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed
[root@test-38 ~]# kubectl get services
NAME                  TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1      <none>        443/TCP          2d17h
kubernetes-bootcamp   NodePort    10.99.65.217   <none>        8080:30691/TCP   8s

現在可以看到我們新運行了一個叫kubernetes-bootcamp的service,可以看到應用被映射到節點的30691端口,端口號是隨機分配的,可以執行如下命令訪問應用:

[root@test-38 ~]# curl localhost:30691
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-57978f5f5d-jcn7k | v=1

Deployment會自動為我們的Pod創建一個標簽

[root@test-38 ~]# kubectl describe deployments

使用標簽獲取pod列表:

[root@test-38 ~]# kubectl get pods -l app=kubernetes-bootcamp
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-57978f5f5d-jcn7k   1/1     Running   0          19h

刪除service——delete service

[root@test-38 ~]# kubectl delete service -l app=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted
2.2.9 Scale 應用

默認情況下只會運行一個副本,可以通過kubectl get deployments查看副本

[root@test-38 ~]# kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           22h

READY 顯示的是當前副本和所需副本的比率
UP-TO-DATE 顯示的是已更新到所需狀態的副本數量
AVAILABLE 顯示應用程序有多少個副本可供用戶使用
AGE 顯示應用程序已運行的時間

現在我們擴展復制集到4個

[root@test-38 ~]# kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.apps/kubernetes-bootcamp scaled
[root@test-38 ~]# kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   4/4     4            4           22h

現在我們查看pod的情況,可以看到當前Pod已經增加到4個

[root@test-38 ~]# kubectl get pods -o wide
NAME                                   READY   STATUS    RESTARTS   AGE     IP          NODE      NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-57978f5f5d-42tp5   1/1     Running   0          2m10s   10.32.0.5   test-38   <none>           <none>
kubernetes-bootcamp-57978f5f5d-8k4w4   1/1     Running   0          2m10s   10.32.0.7   test-38   <none>           <none>
kubernetes-bootcamp-57978f5f5d-jcn7k   1/1     Running   0          22h     10.32.0.4   test-38   <none>           <none>
kubernetes-bootcamp-57978f5f5d-pkfgq   1/1     Running   0          2m10s   10.32.0.6   test-38   <none>           <none>

可以驗證一下復制集是否進行負載均衡,使用curl進行訪問應用,可以各個請求每次發送到不同的Pod,四個副本輪詢處理,實現負載均衡

[root@test-38 ~]# curl localhost:32230
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-57978f5f5d-pkfgq | v=1
[root@test-38 ~]# curl localhost:32230
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-57978f5f5d-jcn7k | v=1
[root@test-38 ~]# curl localhost:32230
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-57978f5f5d-42tp5 | v=1
2.2.10 滾動更新

使用kubectl describe pods 查看現在的image版本信息,現在將image升級到v2

 kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2

通過kubectl get pods可以看到滾動更新的過程:v1的Pod逐漸刪除,同時啟動新的v2 Pod。
回退版本使用kubectl rollout undo命令,rollout命令將部署還原到先前的已知狀態(映像的v2)。 更新是版本控制的,您可以還原到以前任何已知的部署狀態。

kubectl rollout undo deployments/kubernetes-bootcamp

??????????完結撒花~

參考:《Kubenetes權威指南》、https://kubernetes.io

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容