十九、k8s 集群部署
19.1 k8s 快速入門
19.1.1 簡介
Kubernetes 簡稱 k8s。是用于自動部署,擴展和管理容器化應用程序的開源系統。
中文官網
中文社區
官方文檔
社區文檔
概述 | Kubernetes
傳統部署時代:
早期,各個組織是在物理服務器上運行應用程序。 由于無法限制在物理服務器中運行的應用程序資源使用,因此會導致資源分配問題。 例如,如果在同一臺物理服務器上運行多個應用程序, 則可能會出現一個應用程序占用大部分資源的情況,而導致其他應用程序的性能下降。 一種解決方案是將每個應用程序都運行在不同的物理服務器上, 但是當某個應用程序資源利用率不高時,剩余資源無法被分配給其他應用程序, 而且維護許多物理服務器的成本很高。
虛擬化部署時代:
因此,虛擬化技術被引入了。虛擬化技術允許你在單個物理服務器的 CPU 上運行多臺虛擬機(VM)。 虛擬化能使應用程序在不同 VM 之間被彼此隔離,且能提供一定程度的安全性, 因為一個應用程序的信息不能被另一應用程序隨意訪問。
虛擬化技術能夠更好地利用物理服務器的資源,并且因為可輕松地添加或更新應用程序, 而因此可以具有更高的可擴縮性,以及降低硬件成本等等的好處。 通過虛擬化,你可以將一組物理資源呈現為可丟棄的虛擬機集群。
每個 VM 是一臺完整的計算機,在虛擬化硬件之上運行所有組件,包括其自己的操作系統。
容器部署時代:
容器類似于 VM,但是更寬松的隔離特性,使容器之間可以共享操作系統(OS)。 因此,容器比起 VM 被認為是更輕量級的。且與 VM 類似,每個容器都具有自己的文件系統、CPU、內存、進程空間等。 由于它們與基礎架構分離,因此可以跨云和 OS 發行版本進行移植。
容器因具有許多優勢而變得流行起來,例如:
- 敏捷應用程序的創建和部署:與使用 VM 鏡像相比,提高了容器鏡像創建的簡便性和效率。
- 持續開發、集成和部署:通過快速簡單的回滾(由于鏡像不可變性), 提供可靠且頻繁的容器鏡像構建和部署。
- 關注開發與運維的分離:在構建、發布時創建應用程序容器鏡像,而不是在部署時, 從而將應用程序與基礎架構分離。
- 可觀察性:不僅可以顯示 OS 級別的信息和指標,還可以顯示應用程序的運行狀況和其他指標信號。
- 跨開發、測試和生產的環境一致性:在筆記本計算機上也可以和在云中運行一樣的應用程序。
- 跨云和操作系統發行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方運行。
- 以應用程序為中心的管理:提高抽象級別,從在虛擬硬件上運行 OS 到使用邏輯資源在 OS 上運行應用程序。
- 松散耦合、分布式、彈性、解放的微服務:應用程序被分解成較小的獨立部分, 并且可以動態部署和管理 - 而不是在一臺大型單機上整體運行。
- 資源隔離:可預測的應用程序性能。
- 資源利用:高效率和高密度。
2.為什么需要 Kubernetes,它能做什么?
以前使用Swarm Mode方式調度,功能簡單,現在使用Kubernetes
容器是打包和運行應用程序的好方式。在生產環境中, 你需要管理運行著應用程序的容器,并確保服務不會下線。 例如,如果一個容器發生故障,則你需要啟動另一個容器。 如果此行為交由給系統處理,是不是會更容易一些?
這就是 Kubernetes 要來做的事情! Kubernetes 為你提供了一個可彈性運行分布式系統的框架。 Kubernetes 會滿足你的擴展要求、故障轉移你的應用、提供部署模式等。 例如,Kubernetes 可以輕松管理系統的 Canary (金絲雀) 部署。
Kubernetes 為你提供:
-
服務發現和負載均衡
Kubernetes 可以使用 DNS 名稱或自己的 IP 地址來暴露容器。 如果進入容器的流量很大, Kubernetes 可以負載均衡并分配網絡流量,從而使部署穩定。 -
存儲編排
Kubernetes 允許你自動掛載你選擇的存儲系統,例如本地存儲、公共云提供商等。 -
自動部署和回滾
你可以使用 Kubernetes 描述已部署容器的所需狀態, 它可以以受控的速率將實際狀態更改為期望狀態。 例如,你可以自動化 Kubernetes 來為你的部署創建新容器, 刪除現有容器并將它們的所有資源用于新容器。 -
自動完成裝箱計算
你為 Kubernetes 提供許多節點組成的集群,在這個集群上運行容器化的任務。 你告訴 Kubernetes 每個容器需要多少 CPU 和內存 (RAM)。Kubernetes 可以將這些容器按實際情況調度到你的節點上,以最佳方式利用你的資源。 -
自我修復
Kubernetes 將重新啟動失敗的容器、替換容器、殺死不響應用戶定義的運行狀況檢查的容器, 并且在準備好服務之前不將其通告給客戶端。 -
密鑰與配置管理
Kubernetes 允許你存儲和管理敏感信息,例如密碼、OAuth 令牌和 SSH 密鑰。 你可以在不重建容器鏡像的情況下部署和更新密鑰和應用程序配置,也無需在堆棧配置中暴露密鑰。 -
批處理執行?除了服務外,Kubernetes 還可以管理你的批處理和 CI(持續集成)工作負載,如有需要,可以替換失敗的容器。
-
水平擴縮?使用簡單的命令、用戶界面或根據 CPU 使用率自動對你的應用進行擴縮。
-
IPv4/IPv6?雙棧 為 Pod(容器組)和 Service(服務)分配 IPv4 和 IPv6 地址。
-
為可擴展性設計?在不改變上游源代碼的情況下為你的 Kubernetes 集群添加功能。
3.Kubernetes 不是什么
Kubernetes 不是傳統的、包羅萬象的 PaaS(平臺即服務)系統。 由于 Kubernetes 是在容器級別運行,而非在硬件級別,它提供了 PaaS 產品共有的一些普遍適用的功能, 例如部署、擴展、負載均衡,允許用戶集成他們的日志記錄、監控和警報方案。 但是,Kubernetes 不是單體式(monolithic)系統,那些默認解決方案都是可選、可插拔的。 Kubernetes 為構建開發人員平臺提供了基礎,但是在重要的地方保留了用戶選擇權,能有更高的靈活性。
Kubernetes:
- 不限制支持的應用程序類型。 Kubernetes 旨在支持極其多種多樣的工作負載,包括無狀態、有狀態和數據處理工作負載。 如果應用程序可以在容器中運行,那么它應該可以在 Kubernetes 上很好地運行。
- 不部署源代碼,也不構建你的應用程序。 持續集成(CI)、交付和部署(CI/CD)工作流取決于組織的文化和偏好以及技術要求。
- 不提供應用程序級別的服務作為內置服務,例如中間件(例如消息中間件)、 數據處理框架(例如 Spark)、數據庫(例如 MySQL)、緩存、集群存儲系統 (例如 Ceph)。這樣的組件可以在 Kubernetes 上運行,并且/或者可以由運行在 Kubernetes 上的應用程序通過可移植機制(例如開放服務代理)來訪問。
- 不是日志記錄、監視或警報的解決方案。 它集成了一些功能作為概念證明,并提供了收集和導出指標的機制。
- 不提供也不要求配置用的語言、系統(例如 jsonnet),它提供了聲明性 API, 該聲明性 API 可以由任意形式的聲明性規范所構成。
- 不提供也不采用任何全面的機器配置、維護、管理或自我修復系統。
- 此外,Kubernetes 不僅僅是一個編排系統,實際上它消除了編排的需要。 編排的技術定義是執行已定義的工作流程:首先執行 A,然后執行 B,再執行 C。 而 Kubernetes 包含了一組獨立可組合的控制過程,可以持續地將當前狀態驅動到所提供的預期狀態。 你不需要在乎如何從 A 移動到 C,也不需要集中控制,這使得系統更易于使用且功能更強大、 系統更健壯,更為彈性和可擴展。
19.1.2 架構
1.整體主從方式
2.Master 節點架構
- kube-apiserver
- 對外暴露 K8S 的 api 接口,是外界進行資源操作的唯一入口
- 提供認證、授權、訪問控制、API 注冊和發現等機制
- etcd
- etcd 是兼具一致性和高可用性的鍵值數據庫,可以作為保存 Kubernetes 所有集群數據的后臺數據庫。
- Kubernetes 集群的 etcd 數據庫通常需要有個備份計劃
- kube-scheduler
- 主節點上的組件,該組件監視那些新創建的未指定運行節點的 Pod,并選擇節點讓 Pod 在上面運行。
- 所有對 k8s 的集群操作,都必須經過主節點進行調度
- kube-controller-manager
- 在主節點上運行控制器的組件
- 這些控制器包括:
- 節點控制器(Node Controller): 負責在節點出現故障時進行通知和響應。
- 副本控制器(Replication Controller): 負責為系統中的每個副本控制器對象維護正確數量的 Pod。
- 端點控制器(Endpoints Controller): 填充端點(Endpoints)對象(即加入 Service與 Pod)。
- 服務帳戶和令牌控制器(Service Account & Token Controllers): 為新的命名空間創建默認帳戶和 API 訪問令牌
3.Node 節點架構
- kubelet
- 一個在集群中每個節點上運行的代理。它保證容器都運行在 Pod 中。
- 負責維護容器的生命周期,同時也負責 Volume(CSI)和網絡(CNI)的管理;
- kube-proxy
- 負責為 Service 提供 cluster 內部的服務發現和負載均衡;
- 容器運行環境(Container Runtime)
- 容器運行環境是負責運行容器的軟件。
- Kubernetes 支持多個容器運行環境: Docker、 containerd、cri-o、 rktlet 以及任何實現 Kubernetes CRI (容器運行環境接口)。
- fluentd
- 是一個守護進程,它有助于提供集群層面日志 集群層面的日志
19.1.3 概念
-
Container:容器,可以是 docker 啟動的一個容器
-
Pod:
- k8s 使用 Pod 來組織一組容器
- 一個 Pod 中的所有容器共享同一網絡。
- Pod 是 k8s 中的最小部署單元
-
Volume
- 聲明在 Pod 容器中可訪問的文件目錄
- 可以被掛載在 Pod 中一個或多個容器指定路徑下
- 支持多種后端存儲抽象(本地存儲,分布式存儲,云存儲…)
Controllers:更高層次對象,部署和管理 Pod;
- ReplicaSet:確保預期的 Pod 副本數量
- Deplotment:無狀態應用部署
- StatefulSet:有狀態應用部署
- DaemonSet:確保所有 Node 都運行一個指定 Pod
- Job:一次性任務
- Cronjob:定時任務
Deployment:
- 定義一組 Pod 的副本數目、版本等
- 通過控制器(Controller)維持 Pod 數目(自動回復失敗的 Pod)
- 通過控制器以指定的策略控制版本(滾動升級,回滾等)
Service
- 定義一組 Pod 的訪問策略
- Pod 的負載均衡,提供一個或者多個 Pod 的穩定訪問地址
- 支持多種方式(ClusterIP、NodePort、LoadBalance)
Label:標簽,用于對象資源的查詢,篩選
Namespace:命名空間,邏輯隔離
- 一個集群內部的邏輯隔離機制(鑒權,資源)
- 每個資源都屬于一個 namespace
- 同一個 namespace 所有資源名不能重復
- 不同 namespace 可以資源名重復
API:
我們通過 kubernetes 的 API 來操作整個集群。
可以通過 kubectl、ui、curl 最終發送 http+json/yaml 方式的請求給 API Server,然后控制 k8s集群。k8s 里的所有的資源對象都可以采用 yaml 或 JSON 格式的文件定義或描述。
19.1.4 快速體驗
1、安裝 minikube
https://github.com/kubernetes/minikube/releases
下載 minikube-windows-amd64.exe 改名為 minikube.exe
打開 VirtualBox,打開 cmd,
運行
minikube start --vm-driver=virtualbox --registry-mirror=https://registry.docker-cn.com
等待 20 分鐘左右即可
2、體驗 nginx 部署升級
19.1.5 流程敘述
- 通過 Kubectl 提交一個創建 RC(Replication Controller)的請求,該請求通過 APIServer被寫入 etcd 中
- 此時 Controller Manager 通過 API Server 的監聽資源變化的接口監聽到此 RC 事件
- 分析之后,發現當前集群中還沒有它所對應的 Pod 實例,
- 于是根據 RC 里的 Pod 模板定義生成一個 Pod 對象,通過 APIServer 寫入 etcd
- 此事件被 Scheduler 發現,它立即執行一個復雜的調度流程,為這個新 Pod 選定一個落戶的 Node,然后通過 API Server 講這一結果寫入到 etcd 中,
- 目標 Node 上運行的 Kubelet 進程通過 APIServer 監測到這個“新生的”Pod,并按照它的定義,啟動該 Pod 并任勞任怨地負責它的下半生,直到 Pod 的生命結束。
- 隨后,我們通過 Kubectl 提交一個新的映射到該 Pod 的 Service 的創建請求
- ControllerManager 通過 Label 標簽查詢到關聯的 Pod 實例,然后生成 Service 的Endpoints 信息,并通過 APIServer 寫入到 etcd 中,
- 接下來,所有 Node 上運行的 Proxy 進程通過 APIServer 查詢并監聽 Service 對象與其對應的 Endpoints 信息,建立一個軟件方式的負載均衡器來實現 Service 訪問到后端Pod 的流量轉發功能。
k8s 里的所有的資源對象都可以采用 yaml 或 JSON 格式的文件定義或描述
19.2 k8s 集群安裝
19.2.1 kubeadm
kubeadm 是官方社區推出的一個用于快速部署 kubernetes 集群的工具。
這個工具能通過兩條指令完成一個 kubernetes 集群的部署:
-
創建一個 Master 節點
$ kubeadm init -
將一個 Node 節點加入到當前集群中
$ kubeadm join <Master 節點的 IP 和端口 >
19.2.2 前置要求
一臺或多臺機器,操作系統 CentOS7.x-86_x64
硬件配置:2GB 或更多 RAM,2 個 CPU 或更多 CPU,硬盤 30GB 或更多
集群中所有機器之間網絡互通
可以訪問外網,需要拉取鏡像
禁止 swap 分區
19.2.3 部署步驟
- 在所有節點上安裝 Docker 和 kubeadm
- 部署 Kubernetes Master
- 部署容器網絡插件
- 部署 Kubernetes Node,將節點加入 Kubernetes 集群中
- 部署 Dashboard Web 頁面,可視化查看 Kubernetes 資源
19.2.4 環境準備
1、準備工作
- 我們可以使用?VMware?快速創建三個虛擬機。虛擬機啟動前先設置 VMware 的主機網絡。現全部統一為 192.168.119.1,以后所有虛擬機都是 119.x 的 ip 地址
-
設置虛擬機存儲目錄,防止硬盤空間不足
2、啟動三個虛擬機
- 使用我們提供的 vagrant 文件,復制到非中文無空格目錄下,運行 vagrant up 啟動三個虛擬機。其實 vagrant 完全可以一鍵部署全部 k8s 集群。https://github.com/rootsongjc/kubernetes-vagrant-centos-cluster
-
進入三個虛擬機,開啟 root 的密碼訪問權限。
所有虛擬機設置為 node1分配 4g、4C;node2、node3 分配 16g,16C設置好 NAT 網絡
3、設置?linux?環境(三個節點都執行)
關閉防火墻:
systemctl stop firewalld
systemctl disable firewalld
關閉 selinux:
sed -i 's/enforcing/disabled/' /etc/selinux/config
setenforce 0
關閉 swap:
swapoff -a #臨時
sed -ri 's/.*swap.*/#&/' /etc/fstab #永久
free -g #驗證,swap 必須為 0;
添加主機名與 IP 對應關系
vi /etc/hosts
192.168.119.133 k8s-node1
192.168.119.134 k8s-node2
192.168.119.135 k8s-node3hostnamectl set-hostname <newhostname>:指定新的 hostname
su 切換過來
wq保存,然后重啟每臺服務
- 將橋接的 IPv4 流量傳遞到 iptables 的鏈:
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF# 加載參數
sysctl --system
19.2.5 所有節點安裝 Docker、kubeadm、kubelet、kubectl
Kubernetes 默認 CRI(容器運行時)為 Docker,因此先安裝 Docker。
1、安裝 docker
1.卸載系統之前的 docker
# 安裝前先更新yum,不然有可能出現本機無法連接虛擬機的mysql、redis等
sudo yum update
# 卸載系統之前的docker,以及 docker-cli
sudo yum remove docker-ce docker-ce-cli containerd.io
# 卸載系統之前的docker
sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
2.安裝 Docker-CE
(1)、安裝必須的依賴
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
(2)、設置 docker repo 的 yum 位置
# 配置鏡像
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
(3)、安裝 docker,以及 docker-cli
該命令安裝docker以后,kubeadm初始化時會報錯,提示版本不兼容
sudo yum install -y docker-ce docker-ce-cli containerd.io
所以我們使用推薦docker版本
sudo yum install docker-ce-3:19.03.15-3.el7.x86_64 docker-ce-cli-19.03.15-3.el7.x86_64 containerd.io
3.配置 docker 加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://chqac97z.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
4.啟動 docker & 設置 docker 開機自啟
systemctl start docker
systemctl enable docker
基礎環境準備好,可以給三個虛擬機備份一下;為 node1分配 4g、4C;gnode2、node3 分配 16g,16C。方便未來側測試
2、添加阿里云 yum 源
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
3、安裝 kubeadm,kubelet 和 kubectl
yum list|grep kube
yum install -y kubelet-1.17.3 kubeadm-1.17.3 kubectl-1.17.3
systemctl enable kubelet
systemctl start kubelet
19.2.6 部署 k8s-master(master節點)
1.下載鏡像
由于需要下載好多鏡像,我們也不知道下載進入如何,此時我們通過運行提供的腳本來下載鏡像,可以看到下載進度
(1)、上傳k8s文件到主節點
解壓發現沒有該命令unzip,安裝unzip命令
sudo yum update
sudo yum install unzip
(2)、可以看到master_images.sh腳本內容
我們只需要啟動該腳本就可以了
(3)、我們看到master_images.sh腳本沒有執行權限,我們這個時候還不能啟動腳本下載鏡像,修改權限
chmod 700 master_images.sh
(4)、啟動腳本
./master_images.sh
2.master 節點初始化
kubeadm init \
--apiserver-advertise-address=192.168.119.133 \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version v1.17.3 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.244.0.0/16
由于默認拉取鏡像地址 k8s.gcr.io 國內無法訪問,這里指定阿里云鏡像倉庫地址。可以手動
按照我們的 images.sh 先拉取鏡像,地址變為 registry.aliyuncs.com/google_containers 也可以。
科普:無類別域間路由(Classless Inter-Domain Routing、CIDR)是一個用于給用戶分配 IP
地址以及在互聯網上有效地路由 IP 數據包的對 IP 地址進行歸類的方法。
拉取可能失敗,需要下載鏡像。
運行完成提前復制:加入集群的令牌
【注意】
初始化的時候報錯
嘗試推倒重來,重置k8s集群
kubeadm reset
提示是否確認,是。然后成功重置
3.測試 kubectl(主節點執行)
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
獲取所有節點?
kubectl get nodes
目前 master 狀態為 notready。等待網絡加入完成即可。
查看 kubelet 日志
journalctl -u kubelet
先記錄下來,等網絡加入完成才可以在從節點操作
kubeadm join 192.168.119.130:6443 --token qyc2xb.1ygxll0plko0te5n \
--discovery-token-ca-cert-hash sha256:6bfd3aeba6116f586b39f15428e6f358055fb14b819414785f7b4499da9255fb
19.2.7 安裝 Pod 網絡插件(CNI)(master節點)
初始化完成后,對集群進行網絡配置
kubectl apply -f k8s/kube-flannel.yml
kubectl apply -f \
https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
以上地址可能被墻,大家獲取上傳我們下載好的 flannel.yml 運行即可,同時 flannel.yml 中
指定的 images 訪問不到可以去 docker hub 找一個
wget yml 的地址
vi 修改 yml 所有 amd64 的地址都修改了即可。
等待大約 3 分鐘
kubectl get pods -n kube-system 查看指定名稱空間的 pods
kubectl get pods --all-namespaces 查看所有名稱空間的 pods
ip link set cni0 down 如果網絡出現問題,關閉 cni0,重啟虛擬機繼續測試
執行 watch kubectl get pod -n kube-system -o wide 監控 pod 進度
等 3-10 分鐘,完全都是 running 以后繼續
【注意】
問題一:(主節點)
k8s應用flannel狀態為Init:ImagePullBackOff
查看kube-flannel.yml文件時發現quay.io/coreos/flannel:v0.11.0-amd64
quay.io網站目前國內無法訪問
解決方法:
查看kube-flannel.yml需要什么image
[root@k8s-node1 k8s]# grep image kube-flannel.ymlimage: quay.io/coreos/flannel:v0.11.0-amd64image: quay.io/coreos/flannel:v0.11.0-amd64image: quay.io/coreos/flannel:v0.11.0-arm64image: quay.io/coreos/flannel:v0.11.0-arm64image: quay.io/coreos/flannel:v0.11.0-armimage: quay.io/coreos/flannel:v0.11.0-armimage: quay.io/coreos/flannel:v0.11.0-ppc64leimage: quay.io/coreos/flannel:v0.11.0-ppc64leimage: quay.io/coreos/flannel:v0.11.0-s390ximage: quay.io/coreos/flannel:v0.11.0-s390x
下載flannel:v0.11.0-amd64導入到docker中
可以去https://github.com/flannel-io/flannel/releases/tag/v0.11.0官方倉庫下載鏡像
mkdir /opt/cni-plugins
[root@k8s-node1 cni-plugins]# docker load < flanneld-v0.11.0-amd64.docker
7bff100f35cb: Loading layer [==================================================>] 4.672MB/4.672MB
5d3f68f6da8f: Loading layer [==================================================>] 9.526MB/9.526MB
9b48060f404d: Loading layer [==================================================>] 5.912MB/5.912MB
3f3a4ce2b719: Loading layer [==================================================>] 35.25MB/35.25MB
9ce0bb155166: Loading layer [==================================================>] 5.12kB/5.12kB
Loaded image: quay.io/coreos/flannel:v0.11.0-amd64
[root@k8s-node1 cni-plugins]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy v1.17.3 ae853e93800d 4 years ago 116MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver v1.17.3 90d27391b780 4 years ago 171MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager v1.17.3 b0f1517c1f4b 4 years ago 161MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler v1.17.3 d109c0821a2b 4 years ago 94.4MB
registry.cn-hangzhou.aliyuncs.com/google_containers/coredns 1.6.5 70f311871ae1 4 years ago 41.6MB
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd 3.4.3-0 303ce5db0e90 4 years ago 288MB
quay.io/coreos/flannel v0.11.0-amd64 ff281650a721 5 years ago 52.6MB
registry.cn-hangzhou.aliyuncs.com/google_containers/pause 3.1 da86e6ba6ca1 6 years ago 742kB
修改本地Linux上的kube-flannel.yml文件:
?
最后刷新pod
kubectl apply -f kube-flannel.yml
結果:
問題二:(所有節點)
執行完畢后,問題表現為coredns無法啟動,master與node1處于NotReady狀態,如圖所示:
原因排查:
-
對有問題的pod進行describe
報錯顯示:2個節點都有污點,因此無法調度,于是對k8s-node1進行排查
kubectl describe po coredns-7f9c544f75-cx56n -n kube-system|less
-
對node1進行describe
kubectl describe nodes k8s-node1|less
發現錯誤如下:
KubeletNotReady runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
由此推斷是Kubelet沒有部署好,并且是網絡插件導致的,因此對Kubelet進行打印
journalctl -u kubelet --since today | less
6月 16 22:18:26 k8s-node1 kubelet[49627]: : [failed to find plugin "flannel" in path [/opt/cni/bin]] 6月 16 22:18:26 k8s-node1 kubelet[49627]: W0616 22:18:26.884471 49627 cni.go:237] Unable to update cni config: no valid networks found in /etc/cni/net.d 6月 16 22:18:28 k8s-node1 kubelet[49627]: E0616 22:18:28.582488 49627 pod_workers.go:191] Error syncing pod 815f19d1-da0d-467f-a16b-79193ccbae39 ("kube-flannel-ds-lqhbw_kube-flannel(815f19d1-da0d-467f-a16b -79193ccbae39)"), skipping: failed to "StartContainer" for "install-cni-plugin" with ImagePullBackOff: "Back-off pulling image \"docker.io/flannel/flannel-cni-plugin:v1.4.1-flannel1\"" 6月 16 22:18:31 k8s-node1 kubelet[49627]: W0616 22:18:31.887401 49627 cni.go:202] Error validating CNI config list { 6月 16 22:18:31 k8s-node1 kubelet[49627]: "name": "cbr0", 6月 16 22:18:31 k8s-node1 kubelet[49627]: "cniVersion": "0.3.1", 6月 16 22:18:31 k8s-node1 kubelet[49627]: "plugins": [ 6月 16 22:18:31 k8s-node1 kubelet[49627]: { 6月 16 22:18:31 k8s-node1 kubelet[49627]: "type": "flannel", 6月 16 22:18:31 k8s-node1 kubelet[49627]: "delegate": { 6月 16 22:18:31 k8s-node1 kubelet[49627]: "hairpinMode": true, 6月 16 22:18:31 k8s-node1 kubelet[49627]: "isDefaultGateway": true 6月 16 22:18:31 k8s-node1 kubelet[49627]: } 6月 16 22:18:31 k8s-node1 kubelet[49627]: }, 6月 16 22:18:31 k8s-node1 kubelet[49627]: { 6月 16 22:18:31 k8s-node1 kubelet[49627]: "type": "portmap", 6月 16 22:18:31 k8s-node1 kubelet[49627]: "capabilities": { 6月 16 22:18:31 k8s-node1 kubelet[49627]: "portMappings": true 6月 16 22:18:31 k8s-node1 kubelet[49627]: } 6月 16 22:18:31 k8s-node1 kubelet[49627]: } 6月 16 22:18:31 k8s-node1 kubelet[49627]: ] 6月 16 22:18:31 k8s-node1 kubelet[49627]: }
最終定位問題至flannel問題
報錯:failed to find plugin “flannel” in path /opt/cni/bin
又在網上差了一些資料,得到解決方案
解決方法:
Github 手動下載 cni plugin v0.8.6
地址如下:https://github.com/containernetworking/plugins/releases/download/v0.8.6/cni-plugins-linux-amd64-v0.8.6.tgz
mkdir /opt/cni-plugins tar -zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni-plugins/ cp flannel /opt/cni/bin/
容器瞬間啟動,master節點處于Ready狀態。同理,k8s-node2,k8s-node3進行同樣操作。問題解決。
19.2.8 加入 Kubernetes Node(從節點)
在 Node 節點執行。
向集群添加新節點,執行在 kubeadm init 輸出的 kubeadm join 命令:
確保 node 節點成功
token 過期怎么辦
kubeadm token create --print-join-command
kubeadm token create --ttl 0 --print-join-command
kubeadm join 192.168.119.130:6443 --token oqnc6s.wiqeib0osvp37yxg --discovery-token-ca-cert-hash sha256:b3e6f39c9b70eece87cc9d29c32b42b4d0d2db930383e2e799208c07b489979d
執行 watch kubectl get pod -n kube-system -o wide 監控 pod 進度
等 3-10 分鐘,完全都是 running 以后使用 kubectl get nodes 檢查狀態
執行命令報錯
[root@k8s-node1 k8s]# kubeadm join 192.168.119.130:6443 --token enj3vg.fikkr30njmptrtem \
> --discovery-token-ca-cert-hash sha256:b7b3baf3082e0d9acd3a0a4f2352224ecb007da583bcc02861f36956c9f017c1
W0605 11:06:13.897366 36607 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.
[preflight] Running pre-flight checks[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
error execution phase preflight: [preflight] Some fatal errors occurred:[ERROR DirAvailable--etc-kubernetes-manifests]: /etc/kubernetes/manifests is not empty[ERROR FileAvailable--etc-kubernetes-kubelet.conf]: /etc/kubernetes/kubelet.conf already exists[ERROR Port-10250]: Port 10250 is in use[ERROR FileAvailable--etc-kubernetes-pki-ca.crt]: /etc/kubernetes/pki/ca.crt already exists
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher
- 問題一
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
報錯原因:
在kubeadm join 添加工作節點時出現docker 驅動cgroup的問題。檢測到"cgroupfs"作為Docker的cgroup驅動程序,推薦使用systemd驅動。解決辦法:
-
修改前先查看驅動信息
docker info | grep Cgrou
-
修改/etc/docker/daemon.json文件
vi /etc/docker/daemon.json #添加以下信息 {"exec-opts":["native.cgroupdriver=systemd"] }
-
重啟docker
systemctl restart docker
-
確認下修改后的驅動信息
- 問題二
[ERROR FileAvailable--etc-kubernetes-kubelet.conf]: /etc/kubernetes/kubelet.conf already exists [ERROR FileAvailable--etc-kubernetes-pki-ca.crt]: /etc/kubernetes/pki/ca.crt already exists
報錯原因:
有殘留文件
解決辦法
#刪除k8s配置文件和證書文件 rm -rf /etc/kubernetes/kubelet.conf /etc/kubernetes/pki/ca.crt
-
問題三
端口占用提示:[ERROR Port-10250]: Port 10250 is in usesudo yum install -y net-tools -q #安裝相關工具(-q:靜默安裝)
然后查看端口
可以看出,是K8S占用了,那就嘗試重啟服務看看能不能解決
19.2.9 入門操作 kubernetes 集群
1、部署一個 tomcat
kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8
kubectl get pods -o wide #可以獲取到 tomcat 信息
2、暴露 tomcat 訪問
kubectl expose deployment tomcat6 --port=80 --target-port=8080 --type=NodePort
現在我們使用NodePort的方式暴露,這樣訪問每個節點的端口,都可以訪問各個Pod,如果節點宕機,就會出現問題。
Pod 的 80 映射容器的 8080;service 會代理 Pod 的 80
kubectl get svc
3、動態擴容測試
kubectl get deployment
應用升級 kubectl set image (–help 查看幫助)
擴容:
kubectl scale --replicas=3 deployment tomcat6
擴容了多份,所有無論訪問哪個 node 的指定端口,都可以訪問到 tomcat6
4、以上操作的 yaml 獲取
參照 k8s 細節
5、刪除
kubectl get all
kubectl delete deployment.apps/tomcat6
kubectl delete service/tomcat6
流程;創建 deployment 會管理 replicas,replicas 控制 pod 數量,有 pod 故障會自動拉起新的 pod
19.2.10 安裝默認 dashboard
1、部署 dashboard
kubectl apply -f \
https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommende
d/kubernetes-dashboard.yaml
墻的原因,文件已經放在我們的 code 目錄,自行上傳
文件中無法訪問的鏡像,自行去 docker hub 找
2、暴露 dashboard 為公共訪問
默認 Dashboard 只能集群內部訪問,修改 Service 為 NodePort 類型,暴露到外部:
kind: Service
apiVersion: v1
metadata:
labels:k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
type: NodePort
ports:- port: 443targetPort: 8443nodePort: 30001
selector:k8s-app: kubernetes-dashboard
訪問地址:http://NodeIP:30001
3、創建授權賬戶
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk
'/dashboard-admin/{print $1}')
使用輸出的 token 登錄 Dashboard。
20、K8S 細節
20.1 kubectl
-
kubectl 文檔
命令行工具 (kubectl) | Kubernetes -
資源類型
命令行工具 (kubectl) | Kubernetes -
格式化輸出
命令行工具 (kubectl) | Kubernetes -
常用操作
命令行工具 (kubectl) | Kubernetes -
命令參考
Kubectl Reference Docs
20.2 yaml 語法
1.yml 模板
2.yaml 字段解析
參照官方文檔:
命令行工具 (kubectl) | Kubernetes
3.yaml輸出
在此示例中,以下命令將單個 pod 的詳細信息輸出為 YAML 格式的對象:
kubectl get pod web-pod-13je7 -o yaml
–dry-run:
–dry-run=‘none’: Must be “none”, “server”, or “client”. If client strategy, only print the object that would be sent, without sending it. If server strategy, submit server-side request without persisting the resource. 值必須為,或。
none
server:提交服務器端請求而不持久化資源。
client:只打印該發送對象,但不發送它。
也就是說,通過–dry-run選項,并不會真正的執行這條命令。
輸出yaml案例
kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8 --dry-run -o yaml > tomact6-deployment.yaml
查看yaml:cat tomact6-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: tomcat6name: tomcat6
spec:replicas: 1selector:matchLabels:app: tomcat6strategy: {}template:metadata:creationTimestamp: nulllabels:app: tomcat6spec:containers:- image: tomcat:6.0.53-jre8name: tomcatresources: {}
status: {}
20.3 入門操作
1.Pod 是什么,Controller 是什么
Pod | Kubernetes
Pod和控制器
控制器可以為您創建和管理多個 Pod,管理副本和上線,并在集群范圍內提供自修復能力。
例如,如果一個節點失敗,控制器可以在不同的節點上調度一樣的替身來自動替換 Pod。
包含一個或多個 Pod 的控制器一些示例包括:
Deployment
StatefulSet
DaemonSet
控制器通常使用您提供的 Pod 模板來創建它所負責的 Pod
2.Deployment&Service 是什么
3.Service 的意義
- 部署一個 nginx
kubectl create deployment nginx --image=nginx -
暴露 nginx 訪問
kubectl expose deployment nginx --port=80 --type=NodePort
統一應用訪問入口;
Service 管理一組 Pod。
防止 Pod 失聯(服務發現)、定義一組 Pod 的訪問策略
現在 Service 我們使用 NodePort 的方式暴露,這樣訪問每個節點的端口,都可以訪問到這個 Pod,如果節點宕機,就會出現問題。
4.labels and selectors
5.Ingress
通過 Service 發現 Pod 進行關聯。基于域名訪問。
通過 Ingress Controller 實現 Pod 負載均衡
支持 TCP/UDP 4 層負載均衡和 HTTP 7 層負載均衡
步驟:
1)、部署 Ingress Controller
2)、創建 Ingress 規則
apiVersion: extensions/v1beta1
kind: Ingress
metadata:name: web
spec:rules:- host: tomcat6.atguigu.comhttp:paths:- backend:serviceName: tomcat6servicePort: 80
如果再部署了 tomcat8;看效果;
kubectl create deployment tomcat8 --image=tomcat:8.5.51-jdk8
kubectl expose deployment tomcat8 --port=88 --target-port=8080 --type=NodePort
kubectl delete xxx #刪除指定資源
隨便配置域名對應哪個節點,都可以訪問 tomcat6/8;因為所有節點的 ingress-controller 路由表是同步的。
6.網絡模型
Kubernetes 的網絡模型從內至外由四個部分組成:
- Pod 內部容器所在的網絡
- Pod 所在的網絡
- Pod 和 Service 之間通信的網絡
- 外界與 Service 之間通信的網絡
20.4 項目部署
項目部署流程:
- 制作項目鏡像(將項目制作為 Docker 鏡像,要熟悉 Dockerfile 的編寫)
- 控制器管理 Pod(編寫 k8s 的 yaml 即可)
- 暴露應用
- 日志監控
接下來我們還是以原先部署tomact6為實例
創建yaml
kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8 --dry-run -o yaml > tomact6-deployment.yaml
修改yaml
vi tomact6-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: tomcat6name: tomcat6
spec:replicas: 3selector:matchLabels:app: tomcat6template:metadata:labels:app: tomcat6spec:containers:- image: tomcat:6.0.53-jre8name: tomcat
- 應用 tomact6-deployment.yaml 部署tomact6
kubectl apply -f tomact6-deployment.yaml
查看某個pod的具體信息:
[root@k8s-node1 k8s]# kubectl get pods NAME READY STATUS RESTARTS AGE tomcat6-5f7ccf4cb9-qrnvh 1/1 Running 0 11h tomcat6-5f7ccf4cb9-sb6jg 1/1 Running 0 11h tomcat6-5f7ccf4cb9-xsxsx 1/1 Running 0 11h [root@k8s-node1 k8s]# kubectl get pods tomcat6-5f7ccf4cb9-qrnvh -o yaml
-
暴露 tomcat6 訪問
前面我們通過命令行的方式,部署和暴露了tomcat,實際上也可以通過yaml的方式來完成這些操作。暴露端口也通過yaml,生成yaml,并部署kubectl expose deployment tomcat6 --port=80 --target-port=8080 --type=NodePort --dry-run -o yaml
-
整合 tomact6-deployment.yaml - 關聯部署和service
將這段輸出和“tomcat6-deployment.yaml”用—進行拼接,表示部署完畢并進行暴露服務:
vi tomact6-deployment.yaml
apiVersion: apps/v1 kind: Deployment #部署 metadata:labels:app: tomcat6 #標簽name: tomcat6 spec:replicas: 3 #副本數selector:matchLabels:app: tomcat6template:metadata:labels:app: tomcat6spec:containers:- image: tomcat:6.0.53-jre8name: tomcat --- apiVersion: v1 kind: Service metadata:labels:app: tomcat6 #標簽name: tomcat6 spec:ports:- port: 80protocol: TCPtargetPort: 8080selector:app: tomcat6 #標簽type: NodePort
上面類型一個是Deployment,一個是Service
- 刪除以前的部署
kubectl get all kubectl delete deployment.apps/tomcat6
-
部署并暴露服務
kubectl apply -f tomact6-deployment.yaml
查看服務和部署信息
測試
訪問k8s-node1,k8s-node1和k8s-node3的30952端口:隨便訪問一個地址:http://192.168.119.132:30952/現在的問題是service的3個pod都可以訪問,但怎么創建個總的管理者,以便負載均衡
-
部署Ingeress
通過Ingress發現pod進行關聯。基于域名訪問
通過Ingress controller實現POD負載均衡
支持TCP/UDP 4層負載均衡和HTTP 7層負載均衡? ? ?
可以把ingress理解為nginx,通過域名訪問service端口
- Ingress管理多個service
- service管理多個pod
步驟:
1)、部署Ingress controller主節點執行“k8s/ingress-controller.yaml”,
cd k8s kubectl apply -f ingress-controller.yaml
查看
這里master節點負責調度,具體執行交給node2和node3來完成
2)、創建Ingress規則
vi ingress-tomact6.yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata:name: web spec:rules:- host: tomcat6.atguigu.comhttp:paths:- backend:serviceName: tomcat6servicePort: 80
執行
kubectl apply -f ingress-tomact6.yaml
修改本機的hosts文件,添加如下的域名轉換規則:
修改“C:\Windows\System32\drivers\etc\hosts”192.168.56.100 tomact6.atguigu.com 192.168.56.101 tomact6.atguigu.com 192.168.56.102 tomact6.atguigu.com
訪問:http://tomact6.atguigu.com:30952/
并且集群中即便有一個節點不可用,也不影響整體的運行。
21、KubeSphere
默認的 dashboard 沒啥用,我們用 kubesphere 可以打通全部的 devops 鏈路。
Kubesphere 集成了很多套件,集群要求較高
https://kubesphere.io/
Kuboard 也很不錯,集群要求不高
https://kuboard.cn/support/
21.1 簡介
KubeSphere 是一款面向云原生設計的開源項目,在目前主流容器調度平臺 Kubernetes 之上構建的分布式多租戶容器管理平臺,提供簡單易用的操作界面以及向導式操作方式,在降低用戶使用容器調度平臺學習成本的同時,極大降低開發、測試、運維的日常工作的復雜度。
21.2 安裝
21.2.1 前提條件
https://v2-1.docs.kubesphere.io/docs/zh-CN/installation/prerequisites/
21.2.2 安裝前提環境
Helm 是 Kubernetes 的包管理器。包管理器類似于我們在 Ubuntu 中使用的 apt、Centos中使用的 yum 或者 Python 中的 pip 一樣,能快速查找、下載和安裝軟件包。Helm 由客戶端組件 helm 和服務端組件 Tiller 組成, 能夠將一組 K8S 資源打包統一管理, 是查找、共享和使用為 Kubernetes 構建的軟件的最佳方式
1)、安裝