美文网首页程序员
VirtualBox配置虚拟机集群

VirtualBox配置虚拟机集群

作者: Lyudmilalala | 来源:发表于2022-07-05 10:16 被阅读0次

    下载并安装virtualbox

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

    下载镜像

    需要iso格式的光盘
    ubuntu https://ubuntu.com/download/server 注意下载的是光盘还是种子

    新建虚拟机

    点击新建开始创建一个虚拟机

    1.png

    选择内存和磁盘大小

    有一点要记住的是kubernetes集群里的机器需要至少2个CPU

    2.png
    3.png

    在新建的虚拟机是关闭的状态时,点击设置

    选择存储,选择控制器下的光驱后,右边分配光驱选择第一TDR控制器主通道,点击右侧光盘选择选择虚拟盘,导入之前下载的ubuntu镜像iso

    4.png

    选择系统,修改启动顺序,去掉软驱,将硬盘移到光盘前,否则每次关机重启后,不会读取已经保存在硬盘上的文件,而是会重新加载光驱安装系统

    5.png

    如果分配的磁盘空间不够,安装会卡在挂载磁盘的那一步,一般4MB内存需要挂载8G磁盘

    有时候会报错Failed unmounted /cdrom,这种情况有时候是安装的光盘自动弹出了,没有关系,有的时候需要操作一下,可能可行的操作包括:

    1. 手动弹出光盘再继续

    2. 关闭声音

    6.png
    1. 设置系统
    7.png
    8.png
    9.png

    Install和Install completely后的udpate阶段都有可能比较慢,需要耐心等待

    添加增强功能

    增强功能可以帮我们添加自动缩放虚拟机屏幕,共享剪切板,共享文件夹,拖拽等功能

    核心操作是安装VBoxGuestAdditions光盘

    基本操作为关闭虚拟机 -> 在设置/存储中弹出控制器里的光盘 -> 启动虚拟机 -> 选择菜单中的安装增强功能

    10.png 11.png

    登录账号,首先为了防止光盘安装失败,需要先更新系统并安装一些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版本
    

    如果是桌面版虚拟机,这时候要点击出现在桌面的光盘进行安装。

    桌面版.png

    如果是命令行,要挂载对应的光盘,并使用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后窗口可以自动变换大小或者自定义像素比例,然而就算我的文件夹和剪切板都可以使用后,自动缩放屏幕仍然不能工作

    12.png

    有人说调整Display里的显卡和3D加速可以生效,但是我试了也都没有用

    13.png

    最后想到一个勉强能用的方法是改变窗口的百分比,就可以看得清了

    14.png

    共享剪切板

    需要安装了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

    选择共享文件夹,填写挂载卷轴相关的信息

    15.png 16.png

    在虚拟机内sudo reboot后可以看到共享文件夹,注意文件夹的所有者为root

    配置网络

    选择网络,网卡1选择NAT;网卡2选择桥接网络,高级选项里混杂模式选择全部允许

    网卡1.png
    网卡2.png

    需要注意的是,进入虚拟机后必须要安装对应的网络工具才能查看本地ip,比如ubuntu必须要先运行apt install net-tools

    查看虚拟机ip

    虚拟机.png

    主机连接虚拟机

    主机连虚拟机.png

    固定虚拟机的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和之前的版本操作逻辑有很大区别,因此下载时最好提前明确指定版本。

    拷贝并生成好几台虚拟机

    右键 -> 复制

    18.png

    按照网络配置里记录的修改新机器的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里解决

    配置好后可以查看集群信息

    cluster info.png

    这时可以看到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
    

    可能发生如下状况

    flannel-bug.png

    这时需要查看出错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
    
    17.png

    碰到一个奇怪的问题,就是在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的默认页面

    相关文章

      网友评论

        本文标题:VirtualBox配置虚拟机集群

        本文链接:https://www.haomeiwen.com/subject/uagvvrtx.html