使用 kubeadm 创建 Kubernetes 集群


使用 kubeadm 创建 Kubernetes 集群

本文记录了使用 kubeadm 从头搭建一个使用 docker 作为容器运行时的 Kubernetes 集群的过程。

kubeadm 的源代码,直接就在 kubernetes/cmd/kubeadm 目录下,是kubernetes项目的一部分。

kubeadm几乎完全是一位高中生的作品。他叫Lucas Käldström,芬兰人,kubeadm 是他17岁时用业余时间完成的一个社区项目。

Kubeadm是什么

Kubeadm 是一个命令行工具,它主要提供了 kubeadm init 以及 kubeadm join这两个命令来快速创建和初始化kubernetes 集群。

Kubeadm 通过执行必要的操作来启动和运行一个最小可用的集群。它被故意设计为只关心启动集群,而不是之前的节点准备工作。同样的,诸如安装各种各样的插件,例如 Kubernetes Dashboard、监控解决方案以及特定云提供商的插件,这些都不在它负责的范围。

实践环境

本次实验用到的机器如下:

主机名 系统版本 配置 IP 角色
k8s-master CentOS 7.9 64bit 2C4G 172.31.0.2 master
k8s-node1 CentOS 7.9 64bit 2C4G 172.31.0.3 worker
k8s-node2 CentOS 7.9 64bit 2C4G 172.31.0.4 worker

软件版本:

  • Docker:Docker-ce-20.10.7,Docker-ce-cli-20.10.7,Containerd.io-1.4.6

  • Kubernetes version:v1.20.9

  • Calico:3.21

开始之前

  • 每台机器 2 GB 或更多的 RAM(如果少于这个数字将会影响你应用的运行内存)

  • 每台机器 CPU 2 核心及以上

  • 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)

  • 禁用交换分区。为了保证 kubelet 正常工作,你 必须 禁用交换分区

相关环境的搭建和初始化笔者这里先行略过,可以选择阿里云、青云等

以下内容均使用root账户安装和配置。

安装指导

安装Docker(所有节点)

  • 配置 yum 源

    # 安装 yum的工具包
    yum install -y yum-utils
    
    # 配置 docker 的 yum 源,告诉 Linux docker 去哪里下载
    yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  • 安装 docker

    yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7  containerd.io-1.4.6
  • 启动 docker 并设置开机自启动

    systemctl enable docker --now
  • 验证安装成功

    docker info
  • 配置镜像加速器地址

    我们可以注册一个阿里云账号,然后使用阿里云容器镜像服务中的免费镜像

    这里我们额外添加了docker的生产环境核心配置cgroup

    mkdir -p /etc/docker
    
    tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://txuroz75.mirror.aliyuncs.com"],
      "exec-opts": ["native.cgroupdriver=systemd"],
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "100m"
      },
      "storage-driver": "overlay2"
    }
    EOF
    
    systemctl daemon-reload
    systemctl restart docker
  • 验证配置生效

    docker info

k8s 环境准备(所有节点)

  • 设置主机名

    #各个机器设置自己的域名
    hostnamectl set-hostname <myhostname>
    
    # 我自己的三台机器这样设置
    hostnamectl set-hostname k8s-master
    hostnamectl set-hostname k8s-node1
    hostnamectl set-hostname k8s-node2
  • 关闭交换分区

    # 临时关闭
    swapoff -a  
    # 永久关闭
    sed -ri 's/.*swap.*/#&/' /etc/fstab
  • 禁用 SELinux

    将 SELinux 设置为 permissive 模式(相当于将其禁用), 这是允许容器访问主机文件系统所必需的

    # 临时禁用
    setenforce 0
    # 永久禁用
    sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
  • 允许 iptables 检查桥接流量

    cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
    br_netfilter
    EOF
    
    cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    EOF
    
    # 让配置生效
    sudo sysctl --system

安装 kubelet、kubectl、kubeadm(所有节点)

  • 配置 yum 源

    官网提供的 google 源一般用不了,这里直接换成阿里的源

    cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
    [kubernetes]
    name=Kubernetes
    baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
    enabled=1
    gpgcheck=0
    repo_gpgcheck=0
    gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
       http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
    exclude=kubelet kubeadm kubectl
    EOF
  • 执行安装

    # --disableexcludes 禁掉除了kubernetes之外的别的仓库
    # 由于官网未开放同步方式, 替换成阿里源后可能会有索引 gpg 检查失败的情况, 这时请带上`--nogpgcheck`选项安装
    # 指定安装 1.20.9 版本
    
    sudo yum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9 --disableexcludes=kubernetes --nogpgcheck
  • kubelet 设置开机启动

    sudo systemctl enable kubelet --now 

初始化 master 节点(k8s-master)

  • 生成 kubeadm.yaml 文件

    首先导出 kubeadm 配置文件

    kubeadm config print init-defaults --kubeconfig ClusterConfiguration > kubeadm.yml

    查看所需镜像列表

    [root@k8s-master ~]# kubeadm config images list --config kubeadm.yml
    k8s.gcr.io/kube-apiserver:v1.20.0
    k8s.gcr.io/kube-controller-manager:v1.20.0
    k8s.gcr.io/kube-scheduler:v1.20.0
    k8s.gcr.io/kube-proxy:v1.20.0
    k8s.gcr.io/pause:3.2
    k8s.gcr.io/etcd:3.4.13-0
    k8s.gcr.io/coredns:1.7.0
  • 使用国内源拉取所需要的镜像

    其它两个节点需要 kube-proxy ,我们为了方便就全部都安装,所以其它两个节点也执行下面的命令

    sudo tee ./images.sh <<-'EOF'
    #!/bin/bash
    images=(
    kube-apiserver:v1.20.9
    kube-proxy:v1.20.9
    kube-controller-manager:v1.20.9
    kube-scheduler:v1.20.9
    coredns:1.7.0
    etcd:3.4.13-0
    pause:3.2
    )
    for imageName in ${images[@]} ; do
    docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/$imageName
    done
    EOF
       
       
    chmod +x ./images.sh && ./images.sh
  • 执行初始化

    镜像拉取下来后就可以开始安装了,执行以下命令初始化主节点,只在主节点上执行

    #所有机器添加 master 域名映射,以下需要修改为自己的ip,master节点我们也叫做集群入口节点,让所有节点知道 master节点在哪
    echo "172.31.0.2  cluster-endpoint" >> /etc/hosts
    
    #主节点初始化
    # 注意:
    # --apiserver-advertise-address 修改成自己 master 节点机器的ip
    # --control-plane-endpoint 是上面 hosts 映射的值
    # --kubernetes-version 的版本号要对应
    # --service-cidr,--pod-network-cidr 值最好不要修改
    # 所有网络范围不能重叠: --service-cidr,--pod-network-cidr,三台机器ip都不能有重叠
    
    kubeadm init \
    --apiserver-advertise-address=172.31.0.2 \
    --control-plane-endpoint=cluster-endpoint \
    --image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
    --kubernetes-version v1.20.9 \
    --service-cidr=10.96.0.0/16 \
    --pod-network-cidr=192.168.0.0/16

​ 输出如下恭喜你安装成功了

   
# 出现这个就说明安装成功了
Your Kubernetes control-plane has initialized successfully!
# 执行下面的命令配置 kubeconfig
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
# 配置 pod 网络的命令
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/

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
# 哪个机器需要变成主节点执行该命令,这是为了多 master 集群
  kubeadm join cluster-endpoint:6443 --token z9wjde.ewp0hefm2swxupn6 \
    --discovery-token-ca-cert-hash sha256:336a976225818ce72ed9cf1b87bebda2b094f11732a0b622becc5a1b71b733be \
    --control-plane 

Then you can join any number of worker nodes by running the following on each as root:
# 哪个 node 节点想要加入集群需要执行如下指令
kubeadm join cluster-endpoint:6443 --token z9wjde.ewp0hefm2swxupn6 \
    --discovery-token-ca-cert-hash sha256:336a976225818ce72ed9cf1b87bebda2b094f11732a0b622becc5a1b71b733be

​ 按照提示配置 kubeconfig

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

配置好后查看一下 node 状态

[root@k8s-master ~]# kubectl get node
NAME         STATUS     ROLES                  AGE   VERSION
k8s-master   NotReady   control-plane,master   10m   v1.20.9

状态为 NotReady,因为此时还没有安装网络插件。

部署Calico(k8s-master)

注意 Calio 版本需要与 K8s 版本对应,具体要求看 requirements

安装参考官网:install calico

  • 下载配置文件并拉取镜像,只在 master 节点上执行

    curl https://docs.projectcalico.org/archive/v3.21/manifests/calico.yaml -O
  • 部署,只在 master 节点上执行

    kubectl apply -f calico.yaml

    如果不错意外的话等一会 calico 就安装好了,可以通过以下命令查看:

    [root@k8s-master ~]# kubectl get pods -A
    NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
    kube-system   calico-kube-controllers-5bb48c55fd-ghkdz   1/1     Running   0          8m10s
    kube-system   calico-node-6vwgq                          1/1     Running   0          8m10s
    kube-system   coredns-5897cd56c4-kqfn2                   1/1     Running   0          31m
    kube-system   coredns-5897cd56c4-wcgdh                   1/1     Running   0          31m
    kube-system   etcd-k8s-master                            1/1     Running   0          31m
    kube-system   kube-apiserver-k8s-master                  1/1     Running   0          31m
    kube-system   kube-controller-manager-k8s-master         1/1     Running   0          31m
    kube-system   kube-proxy-rnt4v                           1/1     Running   0          31m
    kube-system   kube-scheduler-k8s-master                  1/1     Running   0          31m
    [root@k8s-master ~]# kubectl get node
    NAME         STATUS   ROLES                  AGE   VERSION
    k8s-master   Ready    control-plane,master   32m   v1.20.9

Node节点加入集群(k8s-node1,k8s-node2)

  • 在k8s-node1,k8s-node2上执行该步骤,将节点加入到集群中

先在 k8s-node1 、 k8s-node2节点执行

kubeadm join cluster-endpoint:6443 --token z9wjde.ewp0hefm2swxupn6 \
    --discovery-token-ca-cert-hash sha256:336a976225818ce72ed9cf1b87bebda2b094f11732a0b622becc5a1b71b733be

输出如下:

[root@k8s-node1 ~]# kubeadm join cluster-endpoint:6443 --token z9wjde.ewp0hefm2swxupn6 \
>     --discovery-token-ca-cert-hash sha256:336a976225818ce72ed9cf1b87bebda2b094f11732a0b622becc5a1b71b733be
[preflight] Running pre-flight checks
        [WARNING SystemVerification]: this Docker version is not on the list of validated versions: 20.10.7. Latest validated version: 19.03
        [WARNING Hostname]: hostname "k8s-node1" could not be reached
        [WARNING Hostname]: hostname "k8s-node1": lookup k8s-node1 on 100.64.7.3:53: no such host
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

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.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
  • 检查集群状态,在 k8s-master 上执行

    • 检查各组件运行状态

      [root@k8s-master ~]#  kubectl get cs
      Warning: v1 ComponentStatus is deprecated in v1.19+
      NAME                 STATUS      MESSAGE                                                                                       ERROR
      scheduler            Unhealthy   Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0.1:10251: connect: connection refused   
      controller-manager   Unhealthy   Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0.1:10252: connect: connection refused   
      etcd-0               Healthy     {"health":"true"}   

      参考解决办法 :https://stackoverflow.com/questions/54608441/kubectl-connectivity-issue

      出现这个问题的原因是 /etc/kubernetes/manifests/下的kube-controller-manager.yaml和kube-scheduler.yaml中启动参数设置的默认端口是0。
      解决方法:将相应的--port 0参数注释掉,然后重启kubelet服务即可

      [root@k8s-master manifests]#  kubectl get cs
      Warning: v1 ComponentStatus is deprecated in v1.19+
      NAME                 STATUS    MESSAGE             ERROR
      scheduler            Healthy   ok                  
      controller-manager   Healthy   ok                  
      etcd-0               Healthy   {"health":"true"}  
    • 查看集群信息

      [root@k8s-master ~]# kubectl cluster-info
      Kubernetes control plane is running at https://cluster-endpoint:6443
      KubeDNS is running at https://cluster-endpoint:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
      
      To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
    • 查看节点状态

      [root@k8s-master ~]# kubectl get nodes
      NAME         STATUS   ROLES                  AGE     VERSION
      k8s-master   Ready    control-plane,master   42m     v1.20.9
      k8s-node1    Ready    <none>                 5m15s   v1.20.9
      k8s-node2    Ready    <none>                 5m10s   v1.20.9

补充

kubeadm token

kubeadm init 创建了一个有效期为 24 小时的令牌,过期之后要需要生成新的令牌。

#  --print-join-command  不仅仅打印令牌,而是打印使用令牌加入集群所需的完整 'kubeadm join' 参数。
kubeadm token create --print-join-command

kubernetes dashboard

该步骤只在 master 节点上执行

Dashboard 是基于网页的 Kubernetes 用户界面。您可以使用 Dashboard 将容器应用部署到 Kubernetes 集群中,也可以对容器应用排错,还能管理集群本身及其附属资源。您可以使用 Dashboard 获取运行在集群中的应用的概览信息,也可以创建或者修改 Kubernetes 资源(如 Deployment,Job,DaemonSet 等等)。例如,您可以对 Deployment 实现弹性伸缩、发起滚动升级、重启 Pod 或者使用向导创建新的应用。

  • 下载配置文件

    wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml -O  dashboard.yaml
  • 部署

    kubectl apply -f dashboard.yaml
  • 设置访问端口

    kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard

    type: ClusterIP 改为 type: NodePort

  • 找到端口,在云服务器上的安全组放行

    kubectl get svc -A |grep kubernetes-dashboard
  • 创建访问账号

  • 创建访问账号,准备一个yaml文件; vi dash-user.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: admin-user
      namespace: kubernetes-dashboard
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: admin-user
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: ServiceAccount
      name: admin-user
      namespace: kubernetes-dashboard
  • 部署

    kubectl apply -f dash-user.yaml
  • 获取访问令牌

    kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
  • 三个节点中任何一个节点都可以使用令牌登录

参考资料

install-docker

install-kubeadm

create-cluster-kubeadm

Install Calico

kubeadm-token

kubernetes dashboard


文章作者: 张权
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 张权 !
评论
  目录