VirtualBox配置虛擬機集羣

下載並安裝virtualbox

virtualbox官網 https://www.virtualbox.org/wiki/Downloads

下載鏡像

需要iso格式的光盤
ubuntu https://ubuntu.com/download/server 注意下載的是光盤還是種子

新建虛擬機

點擊新建開始創建一個虛擬機

選擇內存和磁盤大小

有一點要記住的是kubernetes集羣裏的機器需要至少2個CPU


在新建的虛擬機是關閉的狀態時,點擊設置

選擇存儲,選擇控制器下的光驅後,右邊分配光驅選擇第一TDR控制器主通道,點擊右側光盤選擇選擇虛擬盤,導入之前下載的ubuntu鏡像iso

選擇系統,修改啓動順序,去掉軟驅,將硬盤移到光盤前,否則每次關機重啓後,不會讀取已經保存在硬盤上的文件,而是會重新加載光驅安裝系統

如果分配的磁盤空間不夠,安裝會卡在掛載磁盤的那一步,一般4MB內存需要掛載8G磁盤

有時候會報錯Failed unmounted /cdrom,這種情況有時候是安裝的光盤自動彈出了,沒有關係,有的時候需要操作一下,可能可行的操作包括:

  1. 手動彈出光盤再繼續

  2. 關閉聲音

  1. 設置系統


Install和Install completely後的udpate階段都有可能比較慢,需要耐心等待

添加增強功能

增強功能可以幫我們添加自動縮放虛擬機屏幕,共享剪切板,共享文件夾,拖拽等功能

核心操作是安裝VBoxGuestAdditions光盤

基本操作爲關閉虛擬機 -> 在設置/存儲中彈出控制器裏的光盤 -> 啓動虛擬機 -> 選擇菜單中的安裝增強功能

登錄賬號,首先爲了防止光盤安裝失敗,需要先更新系統並安裝一些library

sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get update -y
sudo apt-get install -y dkms build-essential linux-headers-generic linux-headers-$(username -r)
# username -r 獲取當前Linux版本

如果是桌面版虛擬機,這時候要點擊出現在桌面的光盤進行安裝。

如果是命令行,要掛載對應的光盤,並使用root權限進行安裝。

sudo su
mkdir -p /media/cdrom
mount /dev/cdrom /media/cdrom
cd /media/cdrom
sh VBoxLinuxAdditions.run

安裝後記得重啓再查看是否生效

sudo reboot

成功安裝後如果功能沒有自動生效,還要在虛擬機裏額外安裝一些library來啓用功能

sudo apt-get install virtualbox-guest-utils # 據說通用功能都包括
sudo apt-get install virtualbox-guest-dkms # 屏幕縮放
sudo apt-get install virtualbox-guest-x11 # 剪切板和共享文件

但可能會遇到報錯Unable to locate package virtualbox-guest-dkms

如果掛載不生效,我們可能想要把它卸載並重新安裝,這時候可以使用命令

cd /opt/<VirtualBoxAdditions-x.x.xx>/
sudo ./uninstall.sh

如果插入光盤安裝不生效,可以考慮直接下載library安裝

sudo apt-get install virtualbox-guest-additions-iso
# 卸載
sudo apt remove virtualbox-guest-additions-iso && sudo apt autoremove

相關鏈接1
相關鏈接2

屏幕自動縮放

一開始的虛擬機屏幕顯示是很小的,需要放大才能工作

大部分資料的說法都是成功安裝VBox Guest Additions後窗口可以自動變換大小或者自定義像素比例,然而就算我的文件夾和剪切板都可以使用後,自動縮放屏幕仍然不能工作

有人說調整Display裏的顯卡和3D加速可以生效,但是我試了也都沒有用

最後想到一個勉強能用的方法是改變窗口的百分比,就可以看得清了

共享剪切板

需要安裝了VBox Guest Additions才能使用,需要額外安裝virtualbox-guest-x11

sudo apt-get install -y virtualbox-guest-x11

如果不生效可以嘗試運行sudo /usr/bin/VBoxClient --clipboard

共享文件夾

共享文件夾也需要安裝了VBox Guest Additions才能使用,也需要安裝virtualbox-guest-x11

選擇共享文件夾,填寫掛載卷軸相關的信息

在虛擬機內sudo reboot後可以看到共享文件夾,注意文件夾的所有者爲root

配置網絡

選擇網絡,網卡1選擇NAT;網卡2選擇橋接網絡,高級選項裏混雜模式選擇全部允許


需要注意的是,進入虛擬機後必須要安裝對應的網絡工具才能查看本地ip,比如ubuntu必須要先運行apt install net-tools

查看虛擬機ip

主機連接虛擬機

固定虛擬機的IP【會導致無法訪問外網,實現待定】

vim /etc/netplan/00-installer-config.yaml

根據虛擬機ip配置addresses和routes
*注意:addresses是一個列表

network:
    ethernets:
        enp0s3:
            dhcp4: true
        enp0s8:
            dhcp4: no
            addresses: [192.168.1.111/24]
    version: 2

啓用配置

sudo netplan apply

關閉selinux

sed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久
setenforce 0  # 臨時

關閉swap

sed -ri 's/.*swap.*/#&/' /etc/fstab    # 永久
swapoff -a  # 臨時

將橋接的IPv4流量傳遞到iptables的鏈

sudo touch /etc/sysctl.d/k8s.conf
sudo vim /etc/sysctl.d/k8s.conf
# 添加以下內容並保存
# net.bridge.bridge-nf-call-ip6tables = 1
# net.bridge.bridge-nf-call-iptables = 1
# net.ipv4.ip_forward = 1

按照計劃的域名解析ip

sudo vim /etc/hosts
# 添加以下內容並保存
# 192.168.1.111 spinq-master
# 192.168.1.112 spinq-worker1
# 192.168.1.113 spinq-worker2

sudo vim /etc/hostname
# 將值改爲本機計劃的域名
# 或者直接運行命令行 sudo hostnamectl set-hostname kubernetes-master

生效

sysctl --system

配置後測試集羣機器之間ssh能否連通,以及ping www.baidu.com能否成功(保證了可以從公網下載資源)

配置ssh免密登錄

多網卡的情況下需要指定ssh使用的host ip

ssh-keygen生成密鑰對

.ssh文件夾裏vim config添加host配置文件,並寫入以下內容

Host spinq-master
    HostName 192.168.1.111
    User spinq
    Port 22
    IdentityFile /home/spinq/.ssh/id_rsa


Host spinq-worker1
    HostName 192.168.1.112
    User spinq
    Port 22
    IdentityFile /home/spinq/.ssh/id_rsa

安裝docker

唯一要注意的就是ubuntu在20後已經用keyrings代替了原來的apt-key,網上很多教程的sudo curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -寫法是無法正常工作的,不過Docker官方已經做出了正確示例

$ sudo apt-get update
$ sudo apt-get install ca-certificates curl gnupg lsb-release
$ sudo mkdir -p /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ echo  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

kubernetes默認設置cgroup驅動(cgroupdriver)爲"systemd",而docker服務的cgroup驅動默認爲"cgroupfs",建議將其修改爲"systemd",與kubernetes保持一致,

$ docker info # 用來查看cgroup
$ sudo vim /etc/docker/daemon.js
# 添加如下
# {
#   "exec-opts": ["native.cgroupdriver=systemd"]
# }

安裝k8s

$ curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
$ echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
$ sudo apt-get update
$ sudo apt-get install -y kubelet=1.21.14-00 kubeadm=1.21.14-00 kubectl=1.21.14-00

k8s v1.24後棄用dockershim,因此v1.24和之前的版本操作邏輯有很大區別,因此下載時最好提前明確指定版本。

拷貝並生成好幾臺虛擬機

右鍵 -> 複製

按照網絡配置裏記錄的修改新機器的hostname和ip

爲新機器生成新的密鑰,並使用ssh-copy-id -i /home/<username1>/.ssh/id_rsa.pub <username2>@192.168..X.XXX將密鑰分發給其他機器,如果都是root user可以使用ssh-copy-id 192.168.X.XXX

至此新的worker節點上應該:

  1. 配置好了網絡
  2. 添加了ssh key
  3. 安裝了docker和k8s三件套

啓動集羣 【master節點】

k8s v1.24後棄用dockershim,因此v1.24和之前的版本操作邏輯有很大區別

啓動k8s v1.21

啓動k8s需要的鏡像在國內很難下載,所以要預先查看需要的鏡像

kubeadm config images list

並從阿里雲拉取鏡像並改名
需要注意coredns,k8s官方鏡像比阿里雲鏡像多一層repo

docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.21.14
docker pull registry.aliyuncs.com/google_containers/kube-controller-manager:v1.21.14
docker pull registry.aliyuncs.com/google_containers/kube-scheduler:v1.21.14
docker pull registry.aliyuncs.com/google_containers/kube-proxy:v1.21.14
docker pull registry.aliyuncs.com/google_containers/pause:3.4.1
docker pull registry.aliyuncs.com/google_containers/etcd:3.4.13-0
docker pull registry.aliyuncs.com/google_containers/coredns:v1.8.0

docker tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.21.14 k8s.gcr.io/kube-apiserver:v1.21.14
docker tag registry.aliyuncs.com/google_containers/kube-controller-manager:v1.21.14 k8s.gcr.io/kube-controller-manager:v1.21.14
docker tag registry.aliyuncs.com/google_containers/kube-scheduler:v1.21.14 k8s.gcr.io/kube-scheduler:v1.21.14
docker tag registry.aliyuncs.com/google_containers/kube-proxy:v1.21.14 k8s.gcr.io/kube-proxy:v1.21.14
docker tag registry.aliyuncs.com/google_containers/pause:3.4.1 k8s.gcr.io/pause:3.4.1
docker tag registry.aliyuncs.com/google_containers/etcd:3.4.13-0 k8s.gcr.io/etcd:3.4.13-0
docker tag registry.aliyuncs.com/google_containers/coredns:v1.8.0 k8s.gcr.io/coredns/coredns:v1.8.0

預演啓動集羣,發現報錯

$ kubeadm init phase preflight 
[WARNING SystemVerification] missing optional cgroups: blkio
[ERROR NumCPU]: the number of available CPUs 1 is less than the required 2
[ERROR CRI]: container runtime is not running

第二個報錯自行調整虛擬機CPU數量,第三個報錯如下處理後重試

rm /etc/containerd/config.toml
systemctl restart containerd

preflight問題都解決後,重新正式啓動

kubeadm init --kubernetes-version=v1.21.14  --image-repository registry.aliyuncs.com/google_containers --apiserver-advertise-address=192.168.1.111 --pod-network-cidr=192.169.0.0/16 --ignore-preflight-errors=Swap

kubeadm init報錯解決 - 1

除了命令行裏的flag之外,k8s官方現在比較推薦通過config file來配置參數

初始化參數模板可以用

kubeadm config print init-config.yml    # 初始化集羣默認參數
kubeadm config print join-config.yml    # 加入集羣默認參數
# 文件可以不帶後綴,或者寫成.conf, .yaml

參數的詳細解釋見這裏

初始化時調用配置

kubeadm init --config init-config.yml

成功的話會返回類似信息

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:    

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:      
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as 
root:                                                                            root:

kubeadm join 10.0.2.15:6443 --token fb4x67.zk0lses0315xvzla \
        --discovery-token-ca-cert-hash sha256:17167b1f9f4294d12766b1977681f0aa3575b9d978d371aa774fc5b9d978d371aa774fcadc707ff51d

按照指示配置kubeconfig,這樣kubectl纔可以查看到集羣信息

普通user

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

root user

export KUBECONFIG=/etc/kubernetes/admin.conf

root user需要注意的是,如果選擇了設置KUBECONFIG,這個環境變量只是暫時的,機器重啓後kubectl會因爲找不到KUBECONFIG而報如下錯誤

The connection to the server localhost:8080 was refused - did you specify the right host or port?

可以通過把export寫進/etc/profile裏解決

配置好後可以查看集羣信息

這時可以看到master node的狀態是NotReady,需要按指示安裝cni addon

flannel

因爲資源容易被牆,先下載配置文件

wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

然後按照預定的pod cidr決定是否修改參數net-conf.json

net-conf.json: |
    {
      "Network": "10.96.0.0/12",
      "Backend": {
        "Type": "vxlan"
      }
    }

然後將配置文件應用於集羣

$ kubectl apply -f kube-flannel.yml
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

可能發生如下狀況

這時需要查看出錯pod的log

kubectl logs kube-flannel-ds-spw9v -n kube-system

如果遇到Error registering network: failed to acquire lease: node "spinq-master" pod cidr not assigned,說明:

  1. pod cidr沒有配置
  2. pod cidr和kube-flannel.yml中的net-conf.json中的Network參數不一致

解決方法:

  1. 如init集羣時使用配置文件,則確認kube-init-config.ymlkind爲ClusterConfiguration的配置中的networking中的podSubnet參數和kube-flannel.yml中的net-conf.json中的Network參數一致
  2. 如init集羣時使用命令行flag,則確認--pod-network-cidrkube-flannel.yml中的net-conf.json中的Network參數一致

Calico

Calico的quickstart走的不是配置文件的途徑,有些令人費解,希望用熟悉的配置文件方法配置的看這裏

同樣先下載配置文件

https://projectcalico.docs.tigera.io/getting-started/kubernetes/self-managed-onprem/onpremises

Calico的配置需要注意的是,calico-node默認訪問kubernetes SVC的443端口,這將導致無法訪問apiserver,需要在yaml文件添加apiserver的IP和端口

應用配置文件

kubectl apply -f calico.yaml

kubeadm 配置報錯解決 - 1

安裝cni addon成功後kubectl get nodes的結果會變成Ready

$ kubectl get nodes
NAME           STATUS   ROLES                  AGE    VERSION
spinq-master   Ready    control-plane,master   108m   v1.21.14

PS: 如果使用kubeadm reset重置集羣,會提示要刪除/etc/cni/net.d中的cni配置,若刪除了這個文件夾,則下一次kubeadm init會報錯container network is not ready: cni config unitialized,就算再次運行kubectl apply -f calico.yaml也不一定會好,需要systemctl restart kubelet一下,感覺是因爲自動更新機制有問題

可以通過kubectl get pods -A查看其狀態,以及其他所有pod的狀態

也可以通過docker ps查看不同功能的容器是否正常啓動

PS:kubectl get cs的命令的scheduler和controller-manager在各種情況下都有可能爲unhealthy,且已經在v1.19後棄用,因此不需要太擔心詳情

部署基於dockershim的k8s集羣-1
部署基於dockershim的k8s集羣-2

啓動k8s v1.24

事先安裝鏡像

kubeadm config images pull --image-repository=registry.aliyuncs.com/google_containers

k8s v1.24後已經棄用dockershim,默認使用containerd,實際上使用的鏡像要通過crictl img才能查看

ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.24.2 k8s.gcr.io/kube-apiserver:v1.24.2
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/kube-controller-manager:v1.24.2 k8s.gcr.io/kube-controller-manager:v1.24.2
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/kube-scheduler:v1.24.2 k8s.gcr.io/kube-scheduler:v1.24.2
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/kube-proxy:v1.24.2 k8s.gcr.io/kube-proxy:v1.24.2
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/etcd:3.5.3-0 k8s.gcr.io/etcd:3.5.3-0
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/coredns:v1.8.6 k8s.gcr.io/coredns/coredns:v1.8.6

安裝containerd和k8s v1.24 - 1
安裝containerd和k8s v1.24 - 2

kubeadm init --kubernetes-version=v1.24.2  --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr=192.168.0.0/16 --ignore-preflight-errors=Swap

kubelet可以開始運行,但是集羣仍然報錯

systemctl status kubeletjournalctl -xeu kubelet查看日誌,這裏定位問題是需要一些耐心的

發現是包的版本問題,說明之前按照kubeadm config images list查看到的鏡像也並非全部可靠

Jun 28 09:35:57 spinq-master kubelet[10593]: E0628 09:35:57.819736   10593 remote_runtime.go:201] "RunPodSandbox from runtime service failed" err="rpc error: code = Unknown desc = failed to get sandbox image \"k8s.gcr.io/pause:3.6\": failed to pull image \"k8s.gcr.io/pause:3.6\": failed to pull and unpack image \"k8s.gcr.io/pause:3.6\": failed to resolve reference \"k8s.gcr.io/pause:3.6\": failed to do request: Head \"https://k8s.gcr.io/v2/pause/manifests/3.6\": dial tcp 64.233.189.82:443: i/o timeout"

添加需要的包,有關於containerd的操作看這裏

ctr -n k8s.io image pull registry.aliyuncs.com/google_containers/pause:3.6
ctr -n k8s.io image tag registry.aliyuncs.com/google_containers/pause:3.6 k8s.gcr.io/pause:3.6

碰到一個奇怪的問題,就是在k8s集羣啓動後本地ssh虛擬機就容易被拒絕,還未找到原因,後來莫名其妙自己好了

添加節點 【worker節點】

使用init最後產生的命令將worker節點加入集羣

$ kubeadm join 10.0.2.15:6443 --token fb4x67.zk0lses0315xvzla --discovery-token-ca-cert-hash sha256:17167b1f9f4294d12766b1977681f0aa3575b9d978d371aa774fc5b9d978d371aa774fcadc707ff51d
...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

同樣可以通過systemctl status kubeletjournalctl -xeu kubelet來監控節點是否成功啓動,如果無法成功啓動的話,大多數錯誤還是要去master上kubectl describe node或者pod來定位

部署服務

以部署一個nginx服務爲例

k8s服務的基本架構 - 1
k8s服務的基本架構 - 2

將下列配置寫入master節點上的nginx-conf.yml文件

apiVersion: v1
kind: Namespace
metadata:
  name: nginx-demo

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-demo-deploy
  namespace: nginx-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-tag
  template:
    metadata:
      labels:
        app: nginx-tag
    spec:
      containers:
      - name: nginx-ct
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-demo-service
  namespace: nginx-demo
spec:
  type: NodePort
  selector:
    app: nginx-tag # match the template metadata label in Deployment
  ports:
    - protocol: TCP
      port: 3088 # match for service access port
      targetPort: 80 # match for pod access port
      nodePort: 30088 # match for external access port

應用配置文件

$ kubectl apply -f nginx-conf.yml
namespace/nginx-demo unchanged
deployment.apps/nginx-demo-deploy created
service/nginx-demo-service configured

查看生成的pod,deployment,和service
注意kubectl get svc在不標註namesapce的情況下只顯示defaultnamespace下的服務,因此一定要帶-n參數

$ kubectl get pods -n nginx-demo -o wide
NAME                                 READY   STATUS    RESTARTS   AGE   IP            NODE            NOMINATED NODE   READINESS GATES
nginx-demo-deploy-784fb48fbc-kcjpl   1/1     Running   0          18s   10.240.1.11   spinq-worker1   <none>           <none>
nginx-demo-deploy-784fb48fbc-njw9n   1/1     Running   0          18s   10.240.1.10   spinq-worker1   <none>           <none>
$ kubectl get deploy -n nginx-demo
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
nginx-demo-deploy   1/1     1            1           19s
$ kubectl get svc nginx-demo-service -n nginx-demo
NAME                 TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
nginx-demo-service   NodePort   10.109.6.66   <none>        3088:30008/TCP   23s

訪問http://192.168.1.111:30088可以看到nginx的默認頁面

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章