# 使用kubeadm方式搭建K8S集群
kubeadm是官方社區推出的一個用于快速部署kubernetes集群的工具。
這個工具能通過兩條指令完成一個kubernetes集群的部署:
```bash
# 創建一個 Master 節點
kubeadm init
# 將一個 Node 節點加入到當前集群中
kubeadm join <Master節點的IP和端口 >
```
## Kubeadm方式搭建K8S集群
使用kubeadm方式搭建K8s集群主要分為以下幾步
- 準備三臺虛擬機,同時安裝操作系統CentOS 7.x
- 對三個安裝之后的操作系統進行初始化操作
- 在三個節點安裝 docker kubelet kubeadm kubectl
- 在master節點執行kubeadm init命令初始化
- 在node節點上執行 kubeadm join命令,把node節點添加到當前集群
- 配置CNI網絡插件,用于節點之間的連通【失敗了可以多試幾次】
- 通過拉取一個nginx進行測試,能否進行外網測試
## 安裝要求
在開始之前,部署Kubernetes集群機器需要滿足以下幾個條件:
- 一臺或多臺機器,操作系統 CentOS7.x-86_x64
- 硬件配置:2GB或更多RAM,2個CPU或更多CPU,硬盤30GB或更多【注意master需要兩核】
- 可以訪問外網,需要拉取鏡像,如果服務器不能上網,需要提前下載鏡像并導入節點
- 禁止swap分區
## 準備環境
| 角色 | IP |
| ------ | --------------- |
| master | 192.168.177.130 |
| node1 | 192.168.177.131 |
| node2 | 192.168.177.132 |
然后開始在每臺機器上執行下面的命令
```bash
# 關閉防火墻
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
# 根據規劃設置主機名【master節點上操作】
hostnamectl set-hostname k8smaster
# 根據規劃設置主機名【node1節點操作】
hostnamectl set-hostname k8snode1
# 根據規劃設置主機名【node2節點操作】
hostnamectl set-hostname k8snode2
# 在master添加hosts
cat >> /etc/hosts << EOF
192.168.177.130 k8smaster
192.168.177.131 k8snode1
192.168.177.132 k8snode2
EOF
# 將橋接的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
# 時間同步
yum install ntpdate -y
ntpdate time.windows.com
```
## 安裝Docker/kubeadm/kubelet
所有節點安裝Docker/kubeadm/kubelet ,Kubernetes默認CRI(容器運行時)為Docker,因此先安裝Docker
### 安裝Docker
首先配置一下Docker的阿里yum源
```bash
cat >/etc/yum.repos.d/docker.repo<<EOF
[docker-ce-edge]
name=Docker CE Edge - \$basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/\$basearch/edge
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
EOF
```
然后yum方式安裝docker
```bash
# yum安裝
yum -y install docker-ce
# 查看docker版本
docker --version
# 啟動docker
systemctl enable docker
systemctl start docker
```
配置docker的鏡像源
```bash
cat >> /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF
```
然后重啟docker
```bash
systemctl restart docker
```
### 添加kubernetes軟件源
然后我們還需要配置一下yum的k8s軟件源
```bash
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
```
### 安裝kubeadm,kubelet和kubectl
由于版本更新頻繁,這里指定版本號部署:
```bash
# 安裝kubelet、kubeadm、kubectl,同時指定版本
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0
# 設置開機啟動
systemctl enable kubelet
```
## 部署Kubernetes Master【master節點】
在 192.168.177.130 執行,也就是master節點
```bash
kubeadm init --apiserver-advertise-address=192.168.177.130 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.18.0 --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16
```
由于默認拉取鏡像地址k8s.gcr.io國內無法訪問,這里指定阿里云鏡像倉庫地址,【執行上述命令會比較慢,因為后臺其實已經在拉取鏡像了】,我們 docker images 命令即可查看已經拉取的鏡像

當我們出現下面的情況時,表示kubernetes的鏡像已經安裝成功

使用kubectl工具 【master節點操作】
```bash
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
```
執行完成后,我們使用下面命令,查看我們正在運行的節點
```bash
kubectl get nodes
```

能夠看到,目前有一個master節點已經運行了,但是還處于未準備狀態
下面我們還需要在Node節點執行其它的命令,將node1和node2加入到我們的master節點上
## 加入Kubernetes Node【Slave節點】
下面我們需要到 node1 和 node2服務器,執行下面的代碼向集群添加新節點
執行在kubeadm init輸出的kubeadm join命令:
> 注意,以下的命令是在master初始化完成后,每個人的都不一樣!!!需要復制自己生成的
```bash
kubeadm join 192.168.177.130:6443 --token 8j6ui9.gyr4i156u30y80xf \
--discovery-token-ca-cert-hash sha256:eda1380256a62d8733f4bddf926f148e57cf9d1a3a58fb45dd6e80768af5a500
```
默認token有效期為24小時,當過期之后,該token就不可用了。這時就需要重新創建token,操作如下:
```
kubeadm token create --print-join-command
```
當我們把兩個節點都加入進來后,我們就可以去Master節點 執行下面命令查看情況
```bash
kubectl get node
```

## 部署CNI網絡插件
上面的狀態還是NotReady,下面我們需要網絡插件,來進行聯網訪問
```bash
# 下載網絡插件配置
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
```
默認鏡像地址無法訪問,sed命令修改為docker hub鏡像倉庫。
```bash
# 添加
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
##①首先下載v0.13.1-rc2-amd64 鏡像
##參考博客:https://www.cnblogs.com/pyxuexi/p/14288591.html
##② 導入鏡像,命令,,特別提示,3個機器都需要導入,3個機器都需要導入,3個機器都需要導入,3個機器都需要導入,重要的事情說3遍。不然抱錯。如果沒有操作,報錯后,需要刪除節點,重置,在導入鏡像,重新加入才行。本地就是這樣操作成功的!
docker load < flanneld-v0.13.1-rc2-amd64.docker
#####下載本地,替換將image: quay.io/coreos/flannel:v0.13.1-rc2 替換為 image: quay.io/coreos/flannel:v0.13.1-rc2-amd64
# 查看狀態 【kube-system是k8s中的最小單元】
kubectl get pods -n kube-system
```
運行后的結果

運行完成后,我們查看狀態可以發現,已經變成了Ready狀態了

如果上述操作完成后,還存在某個節點處于NotReady狀態,可以在Master將該節點刪除
```bash
# master節點將該節點刪除
##20210223 yan 查閱資料添加###kubectl drain k8snode1 --delete-local-data --force --ignore-daemonsets
kubectl delete node k8snode1
# 然后到k8snode1節點進行重置
kubeadm reset
# 重置完后在加入
kubeadm join 192.168.177.130:6443 --token 8j6ui9.gyr4i156u30y80xf --discovery-token-ca-cert-hash sha256:eda1380256a62d8733f4bddf926f148e57cf9d1a3a58fb45dd6e80768af5a500
```
## 測試kubernetes集群
我們都知道K8S是容器化技術,它可以聯網去下載鏡像,用容器的方式進行啟動
在Kubernetes集群中創建一個pod,驗證是否正常運行:
```bash
# 下載nginx 【會聯網拉取nginx鏡像】
kubectl create deployment nginx --image=nginx
# 查看狀態
kubectl get pod
```
如果我們出現Running狀態的時候,表示已經成功運行了

下面我們就需要將端口暴露出去,讓其它外界能夠訪問
```bash
# 暴露端口
kubectl expose deployment nginx --port=80 --type=NodePort
# 查看一下對外的端口
kubectl get pod,svc
```
能夠看到,我們已經成功暴露了 80端口 到 30529上

我們到我們的宿主機瀏覽器上,訪問如下地址
```bash
http://192.168.177.130:30529/
```
發現我們的nginx已經成功啟動了

到這里為止,我們就搭建了一個單master的k8s集群

## 錯誤匯總
### 錯誤一
在執行Kubernetes init方法的時候,出現這個問題
```bash
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR NumCPU]: the number of available CPUs 1 is less than the required 2
```
是因為VMware設置的核數為1,而K8S需要的最低核數應該是2,調整核數重啟系統即可
### 錯誤二
我們在給node1節點使用 kubernetes join命令的時候,出現以下錯誤
```bash
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR Swap]: running with swap on is not supported. Please disable swap
```
錯誤原因是我們需要關閉swap
```bash
# 關閉swap
# 臨時
swapoff -a
# 臨時
sed -ri 's/.*swap.*/#&/' /etc/fstab
```
### 錯誤三
在給node1節點使用 kubernetes join命令的時候,出現以下錯誤
```bash
The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get http://localhost:10248/healthz: dial tcp [::1]:10248: connect: connection refused
```
解決方法,首先需要到 master 節點,創建一個文件
```bash
# 創建文件夾
mkdir /etc/systemd/system/kubelet.service.d
# 創建文件
vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
# 添加如下內容
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true --fail-swap-on=false"
# 重置
kubeadm reset
```
然后刪除剛剛創建的配置目錄
```bash
rm -rf $HOME/.kube
```
然后 在master重新初始化
```bash
kubeadm init --apiserver-advertise-address=202.193.57.11 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.18.0 --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16
```
初始完成后,我們再到 node1節點,執行 kubeadm join命令,加入到master
```bash
kubeadm join 202.193.57.11:6443 --token c7a7ou.z00fzlb01d76r37s \
--discovery-token-ca-cert-hash sha256:9c3f3cc3f726c6ff8bdff14e46b1a856e3b8a4cbbe30cab185f6c5ee453aeea5
```
添加完成后,我們使用下面命令,查看節點是否成功添加
```bash
kubectl get nodes
```
### 錯誤四
我們再執行查看節點的時候, kubectl get nodes 會出現問題
```bash
Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
```
這是因為我們之前創建的配置文件還存在,也就是這些配置
```bash
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
```
我們需要做的就是把配置文件刪除,然后重新執行一下
```bash
rm -rf $HOME/.kube
```
然后再次創建一下即可
```bash
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
```
這個問題主要是因為我們在執行 kubeadm reset 的時候,沒有把 $HOME/.kube 給移除掉,再次創建時就會出現問題了
### 錯誤五
安裝的時候,出現以下錯誤
```bash
Another app is currently holding the yum lock; waiting for it to exit...
```
是因為yum上鎖占用,解決方法
```bash
yum -y install docker-ce
```
### 錯誤六
在使用下面命令,添加node節點到集群上的時候
```bash
kubeadm join 192.168.177.130:6443 --token jkcz0t.3c40t0bqqz5g8wsb --discovery-token-ca-cert-hash sha256:bc494eeab6b7bac64c0861da16084504626e5a95ba7ede7b9c2dc7571ca4c9e5
```
然后出現了這個錯誤
```bash
[root@k8smaster ~]# kubeadm join 192.168.177.130:6443 --token jkcz0t.3c40t0bqqz5g8wsb --discovery-token-ca-cert-hash sha256:bc494eeab6b7bac64c0861da16084504626e5a95ba7ede7b9c2dc7571ca4c9e5
W1117 06:55:11.220907 11230 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 FileContent--proc-sys-net-ipv4-ip_forward]: /proc/sys/net/ipv4/ip_forward contents are not set to 1
[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
```
出于安全考慮,Linux系統**默認是禁止數據包轉發**的。所謂**轉發即當主機擁有多于一塊的網卡時,其中一塊收到數據包,根據數據包的目的ip地址將包發往本機另一網卡,該網卡根據路由表繼續發送數據包**。這通常就是路由器所要實現的功能。也就是說 **/proc/sys/net/ipv4/ip_forward** 文件的值不支持轉發
- 0:禁止
- 1:轉發
所以我們需要將值修改成1即可
```bash
echo “1” > /proc/sys/net/ipv4/ip_forward
```
修改完成后,重新執行命令即可
- Kubernetes簡介
- 搭建K8S集群前置知識
- 使用kubeadm方式搭建K8S集群
- 使用二進制方式搭建K8S集群
- Kubeadm和二進制方式對比
- Kubernetes集群管理工具kubectl
- Kubernetes集群YAML文件詳解
- Kubernetes核心技術Pod
- Kubernetes核心技術Controller
- Kubernetes核心技術Service
- Kubernetes控制器Controller詳解
- Kubernetes配置管理
- Kubernetes集群安全機制
- Kubernetes核心技術Ingress
- Kubernetes核心技術Helm
- Kubernetes持久化存儲
- Kubernetes集群資源監控
- Kubernetes搭建高可用集群
- Kubernetes容器交付介紹
- 使用kubeadm-ha腳本一鍵安裝K8S
- Kubernetes可視化界面kubesphere
- Kubernetes配置默認存儲類
- 使用Rancher搭建Kubernetes集群
- Kubernetes中的CRI