# 手動建立K8S集群,使用Kubeadm Docker。環境使用virtualBox
###### tags: `K8S`
< https://ithelp.ithome.com.tw/articles/10291343
< https://ithelp.ithome.com.tw/articles/10235069
# 1.建立虛擬機器(1~5步驟)
* Folder欄位建議要更改位置,個人更改成*D:\virtual-box-workspace*
* ISO使用ubuntu-20.04.5-live-server-amd64.iso,[Ubuntu官方下載](https://ubuntu.com/download/server#downloads)
* 完成後按下一步

### 1.1 設定

### 1.2設定虛擬機器cpu & mem
* master node個人使用3cpu & 3096 mem

### 1.3 Ubuntu安裝設定幾乎使用預設,網路方面後續再調整
***我們只安裝open-ssh,其他套件都手動安裝***
profile setup如下:

將openssh加入預設安裝

*只要顯示Install Complete就可以按下stop update & reboot按鈕*
### 1.4 更新成靜態網路
sudo vim /etc/netplan/00-installer-config.yaml
原本使用dhcp4動態網路,我們需要更改成靜態網路

```
network:
ethernets:
enp0s3:
addresses: [192.168.0.103/24]
gateway4: 192.168.0.1
nameservers:
addresses: [8.8.8.8]
version: 2
啟用設定: sudo netplan apply (可以先使用sudo netplan apply try嘗試)
```
### 1.5 請將此台虛擬機器更新網路 (使用橋接介面卡)
設定完之後,就可以使用ssh遠端連線

# 2.K8S建置 (1~x步驟)
### 2.1 k8s不使用swap,所以我們需要將他關閉
```
$ sudo swapoff -a #暫時關閉
$ sudo vim /etc/fstab # 永久關閉
```
個人使用永久關閉,此設定要reboot才啟動

### 2.2 更新repository
```
sudo apt-get update
sudo apt install net-tools ca-certificates curl gnupg lsb-release -y
```
### 2.3 設定DNS,更新host
sudo vim /etc/hosts
```
...
192.168.0.103 k8smaster
192.168.0.104 k8snode1
192.168.0.106 k8snode2
...
```
### 2.4 安裝 docker (version 20.10.12)
```
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
# Issue of The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
sudo gpg --keyserver keyserver.ubuntu.com --recv-keys 7EA0A9C3F273FCD8
gpg -a --export 7EA0A9C3F273FCD8 | sudo apt-key add -
sudo apt install -y docker.io
# sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo docker ps # 確認docker是否運行
# 加入權限,可以不使用sudo就可以執行,要重啟才能使用
sudo groupadd docker
sudo usermod -aG docker $USER
```
#### 2.4.1 Dcoker預設cgroup driver為cgroupfs,K8S使用systemd,修改Docker為systemd
```
sudo bash -c "cat > /etc/docker/daemon.json <<EOF
{
\"exec-opts\": [\"native.cgroupdriver=systemd\"]
}
EOF
"
sudo systemctl restart docker # 重啟
docker info | grep Cgroup # 檢查是否啟用
```
#### 2.4.2 修改Docker為systemd成功

#### 2.4.3 要額外安裝 cri-dockerd,K8S不支援直接使用docker,要透過cri-dockerd方式進行橋接
```
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.2.5/cri-dockerd_0.2.5.3-0.ubuntu-focal_amd64.deb
sudo dpkg -i cri-dockerd_0.2.5.3-0.ubuntu-focal_amd64.deb
cri-dockerd --version # 測試是否完成 version: 0.2.5
```

#### 2.4.4 Service Reload (docker建置完畢)
```
sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl enable --now cri-docker.socket
檢查
sudo systemctl status cri-docker.socket
systemctl status cri-docker.service
```

### 2.5 安裝K8S (version v1.25.5)
#### 2.5.1事前準備
```
sudo apt-get update
sudo apt-get install -y apt-transport-https
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
cat /etc/apt/sources.list.d/kubernetes.list #檢查是否執行成功
```

#### 2.5.2 安裝k8s package
```
sudo apt-get update
sudo apt-get install -y kubelet=1.25.5-00 kubeadm=1.25.5-00 kubectl=1.25.5-00
sudo apt-mark hold kubelet kubeadm kubectl
```
#### 2.5.3 開始建立control panel (建立Node請跳到[2.6](#26-建立k8s-node節點-依照上述不走建置,下面簡單描述))
notes: 我使用過kubelet 1.26.0版本,會跑出It seems like the kubelet isn't running or healthy.錯誤訊息,所以選擇降版本
```
sudo kubeadm init \
--apiserver-advertise-address=192.168.0.113 \
--pod-network-cidr=192.168.1.0/16 \
--cri-socket=unix:///var/run/cri-dockerd.sock \
--service-cidr=192.168.192.0/18
```
###### note: 無法使用cri-socket的話,使用default containerd.sock
```
--cri-socket=unix:///var/run/containerd/containerd.sock
```

#### 2.5.4 複製一份root的憑證資訊到home目錄下
```
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
```
#### 2.5.5 確認K8S Cluster是否建立完畢 (下面兩個步驟完成,代表k8s cluster建置完畢)
1. docker ps

2. kubectl get nodes

3. kubectl get cs

### 2.6 建立k8s node節點 (依照上述不走建置,下面簡單描述)
1. 建立兩台node節點,所以啟用兩台VM (參考步驟1)
2. 參考步驟2建立K8S,只有2.5.3 ~ 2.5.5 以後不需要操作
#### 2.6.1 接下來node加入 k8s集群
```
sudo kubeadm join 192.168.0.113:6443 \
--token p2asek.ictbpusb1mrzox5h \
--discovery-token-ca-cert-hash sha256:1d1f61cc01b2be301385fbe38595f90a9486292972ff58fbfe503c46809a0a06 \
--cri-socket=unix:///var/run/cri-dockerd.sock
```
###### note: 無法使用cri-socket的話,使用default containerd.sock
* 缺點: 無法從docker指令看到container資訊,要使用[crictl](https://kubernetes.io/zh-cn/docs/tasks/debug/debug-cluster/crictl/)取代
* 優點會更快,不依賴docker
> [介紹](https://www.readfog.com/a/1643966909335572480)
```
--cri-socket=unix:///var/run/containerd/containerd.sock
```
#### 2.6.2 node加入成功畫面:

#### 2.6.3 到master中檢查是否node1有加入成功
kubectl get nodes

### 3 K8S建立完成後,建立簡單服務(Nginx)測試
#### 3.1 先建立網路溝通橋樑(Flannel)
```
wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
```
#### 先查看當初建立cluster使用的網路
```
kubectl cluster-info dump | grep -m 1 cluster-cidr
```

更改剛剛下載的檔案: kube-flannel.yml

接下來執行,等待一會後,查看所有node狀態,從NonReady -> Ready
```
kubectl apply -f kube-flannel.yml
```

#### 創立nginx檔案
```
## nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
```
```
## nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
app: nginx
spec:
ports:
- port: 88
targetPort: 80
selector:
app: nginx
type: NodePort
```
```
kubectl apply -f nginx-deployment.yaml
kubectl apply -f nginx-service.yaml
kubectl get pods ## 查看pod是否啟動
kubectl get services ## 查看service是否啟動
```


我們可以看到,nginx server透過Node Port轉發port,所以我們可以透過主機直接進行連線。
#### 創立nginx檔案
```
https://<node-ip>:31369
```

### 4 K8S Dashboard
#### 下載官方recommended.yaml
```
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
```
#### 更新 recommended.yaml
1. 加入hostNetwork: true

2. 加入nodePort

3. 更新k8s dashboard token參數時間,不然15分鐘後就要重新登入,非常痛苦
```
- --token-ttl=604800 ## 一周
```

#### 啟用k8s dashboard與檢查
kubectl get pods -n kubernetes-dashboard

kubectl get services -n kubernetes-dashboard

啟用成功後,與nginx一樣可以透過port 31367直接進行訪問:
```
https://<node-ip>:31367/
```
權限方面按照以下連結進行處理
https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md
成果:

# 錯誤 (未解決)
```
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR CRI]: container runtime is not running: output: time="2023-02-17T10:53:35Z" level=fatal msg="validate service connection: CRI v1 runtime API is not implemented for endpoint \"unix:///var/run/cri-dockerd.sock\": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService"
, error: exit status 1
```
## 指令
```
sudo journalctl -u kubelet -n 100 --no-pager
sudo kubeadm reset --cri-socket /var/run/cri-dockerd.sock
sudo kubeadm join 192.168.0.103:6443 --cri-socket=unix:///var/run/cri-dockerd.sock --token z6rqiu.424abf24xswognoe --discovery-token-ca-cert-hash sha256:16b7a5c9c05a4fb0ebdfd046907f5cf992667d8ca8226b1029e95e3b6365a943
```