首先找到官方文档:Creating a single control-plane cluster with kubeadm

安装 kubeadm

第一步是安装 kubeadm:Installing kubeadm

预检查

  1. 确认机器配置是否达到最低要求;
  2. 检查每个节点的 MAC 地址和 product_uuid 唯一,它们被 Kubernetes 用来区分 node;
  3. 检查 iptables 工具没有使用 nftables 后端,因为 kubeadm 不兼容;
  4. 检查相应端口打开:Check required ports
  5. 检查容器运行时已安装,对于 Docker 或其他最常见的容器运行时,Kubernetes 会做自动适配。

安装 kubeadm, kubelet 和 kubectl

  • kubeadm: 集群安装工具;
  • kubelet: 相当于 Kubernetes 在每个 node 上的代理,管理该节点上的 pods 或者说容器,也负责该节点与集群通讯;
  • kubectl: Kubernetes 命令行工具。
sudo apt-get update && sudo apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

这里会有一个问题,国内无法访问 Google,解决途径是使用国内源,如阿里提供的 https://mirrors.aliyun.com/kubernetes/apt/,以上命令变更为:

sudo apt-get update && sudo apt-get install -y apt-transport-https curl
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

最终 /etc/apt/sources.list.d/kubernetes.list 文件内容如下:

deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main

有关墙内环境可参考:国内源安装kubernetes的工具

额外配置

如果没有使用 Docker,可能需要专门指定 cgroup 驱动:Configure cgroup driver used by kubelet on control-plane node

到这里 kubeadm, kubectl, kubelet 都安装完成了。

初始化集群

kubeadm init 命令用来初始化集群。

kubeadm init 有一些常用的选项,可以参考官方文档:Creating a single control-plane cluster with kubeadm 或者 man page。

有一个选项值得注意,默认 Kubernetes 集群会把当前节点的 IP 绑定为 control plane endpoint,即集群的控制节点地址,但如果要做多个控制节点的高可用集群,或者将来要做(因为 kubeadm 不支持在集群初始化后再改该项配置),就需要在初始化时指定 --control-plane-endpoint 选项来设置所有控制节点的共享 endpoint,它可以是 IP,也可以是 DNS 名,然后,当存在多个控制节点时,可以使用负载均衡将流量按照需求转发到多个控制节点上。

虽然现在只做一个控制节点,但为了以后可能性的考虑,先写一条 hosts 文件 /etc/hosts

<控制节点 IP> cluster-endpoint

再指定好 --control-plane-endpoint 选项,这样最近初始化命令为:

sudo kubeadm init --control-plane-endpoint=cluster-endpoint

这里再次遇到国内无法访问 Google 的问题,解决办法是从国内镜像拉到 kubeadm 需要的镜像,在本地打好 tag,再执行 init 命令。首先用以下命令查看 kubeadm 需要的镜像:

kubeadm config images list

输出:

W1123 18:14:25.607982   27560 version.go:101] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt": Get https://dl.k8s.io/release/stable-1.txt: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
W1123 18:14:25.608087   27560 version.go:102] falling back to the local client version: v1.16.3
k8s.gcr.io/kube-apiserver:v1.16.3
k8s.gcr.io/kube-controller-manager:v1.16.3
k8s.gcr.io/kube-scheduler:v1.16.3
k8s.gcr.io/kube-proxy:v1.16.3
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.3.15-0
k8s.gcr.io/coredns:1.6.2

可以看到,因为连不上 Google,所以根据本地 kubectl 版本使用了 v1.16.3 版本的 Kubernetes 集群,没有关系。

然后我们根据需要从国内源拉取镜像:

images=(
    kube-apiserver:v1.16.3
    kube-controller-manager:v1.16.3
    kube-scheduler:v1.16.3
    kube-proxy:v1.16.3
    pause:3.1
    etcd:3.3.15-0
    coredns:1.6.2
)

for imageName in ${images[@]} ; do
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
    docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
    docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
done

有关墙内环境可参考:kubernetes安装(国内环境)

然后再执行上面的 init 命令就可以成功安装了,有问题再按提示排查。

安装完成后的状态

来看看集群初始化后的状态。

要用非 root 用户用 kubectl 连接集群,需要先把连接信息放到家目录下:

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

集群状态

kubectl version

当前资源类型

kubectl api-resources

查看各种资源类型状态

kubectl get <api-resource>

看看最常见的几种资源类型:

nodes:

kubectl get nodes
NAME             STATUS     ROLES    AGE   VERSION
vm-0-17-ubuntu   NotReady   master   45m   v1.16.3

services:

kubectl get services --all-namespaces
NAMESPACE     NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes   ClusterIP   10.96.0.1    %lt;none>        443/TCP                  75m
kube-system   kube-dns     ClusterIP   10.96.0.10   %lt;none>        53/UDP,53/TCP,9153/TCP   75m

deployments:

kubectl get deployments --all-namespaces
NAMESPACE     NAME      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   coredns   0/2     2            0           75m

pods:

kubectl get pods --all-namespaces
NAMESPACE     NAME                                     READY   STATUS    RESTARTS   AGE
kube-system   coredns-5644d7b6d9-gfc5n                 0/1     Pending   0          75m
kube-system   coredns-5644d7b6d9-hwgkx                 0/1     Pending   0          75m
kube-system   etcd-vm-0-17-ubuntu                      1/1     Running   0          74m
kube-system   kube-apiserver-vm-0-17-ubuntu            1/1     Running   0          74m
kube-system   kube-controller-manager-vm-0-17-ubuntu   1/1     Running   0          74m
kube-system   kube-proxy-pjrnj                         1/1     Running   0          75m
kube-system   kube-scheduler-vm-0-17-ubuntu            1/1     Running   0          74m

看看容器:

docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
65af95e59678        9b65a0f78b09           "/usr/local/bin/kube…"   23 minutes ago      Up 23 minutes                           k8s_kube-proxy_kube-proxy-pjrnj_kube-system_374debbd-be3a-41fc-8b20-6def02d8b0ad_0
c96860f5ccf3        k8s.gcr.io/pause:3.1   "/pause"                 23 minutes ago      Up 23 minutes                           k8s_POD_kube-proxy-pjrnj_kube-system_374debbd-be3a-41fc-8b20-6def02d8b0ad_0
6cff381c2dc5        b2756210eeab           "etcd --advertise-cl…"   23 minutes ago      Up 23 minutes                           k8s_etcd_etcd-vm-0-17-ubuntu_kube-system_7c5d3ec69bde5ca8242d4779ef501e41_0
85af1bb0c317        bb16442bcd94           "kube-controller-man…"   23 minutes ago      Up 23 minutes                           k8s_kube-controller-manager_kube-controller-manager-vm-0-17-ubuntu_kube-system_0b1154f5243d5258a50a606d5ee7bc0e_0
2e369e857caf        df60c7526a3d           "kube-apiserver --ad…"   23 minutes ago      Up 23 minutes                           k8s_kube-apiserver_kube-apiserver-vm-0-17-ubuntu_kube-system_ba06f3cdfcf3e406dd3d85389f51cf30_0
6a2036e9d796        98fecf43a54f           "kube-scheduler --au…"   23 minutes ago      Up 23 minutes                           k8s_kube-scheduler_kube-scheduler-vm-0-17-ubuntu_kube-system_4e1bd6e5b41d60d131353157588ab020_0
315b85913466        k8s.gcr.io/pause:3.1   "/pause"                 23 minutes ago      Up 23 minutes                           k8s_POD_kube-scheduler-vm-0-17-ubuntu_kube-system_4e1bd6e5b41d60d131353157588ab020_0
7448bb4ffaca        k8s.gcr.io/pause:3.1   "/pause"                 23 minutes ago      Up 23 minutes                           k8s_POD_kube-controller-manager-vm-0-17-ubuntu_kube-system_0b1154f5243d5258a50a606d5ee7bc0e_0
76fdc92acc8b        k8s.gcr.io/pause:3.1   "/pause"                 23 minutes ago      Up 23 minutes                           k8s_POD_kube-apiserver-vm-0-17-ubuntu_kube-system_ba06f3cdfcf3e406dd3d85389f51cf30_0
2c5418d1e93e        k8s.gcr.io/pause:3.1   "/pause"                 23 minutes ago      Up 23 minutes                           k8s_POD_etcd-vm-0-17-ubuntu_kube-system_7c5d3ec69bde5ca8242d4779ef501e41_0

这 10 个容器分别是:

  • kube-proxy 相关 * 2
  • etcd 相关 * 2
  • kube-controller 相关 * 2
  • kube-apiserver 相关 * 2
  • kube-scheduler 相关 * 2

可以看到初始化的集群有两个服务,一个部署,7 个 pods,通过 CRI 启动了 10 个容器。

这其中有两个 pods 状态为 Pending,因为网络插件没有配置,集群 DNS 无法启动,需要根据需求选择网络插件安装后才可以开始 DNS。

Calico 为例:

kubectl apply -f https://docs.projectcalico.org/v3.10/manifests/calico.yaml

也可以把 yaml 文件下载到本地再安装。

查看输出,可以看到 Calico 创建了 configmap, serviceaccount, deployment 及其他很多扩展的资源,再检查一下集群的状况,能看到多了 1 个 deployment,2 个 pods,同时 coredns 部署的状态也变为 Ready 了。

Calico 比较特殊,因为它是允许部署到控制节点上的,如果集群中只有管理节点,没有工作节点,那在部署其他应用的时候会发现无法部署,因为管理节点默认只能部署管理用的 pods,要把其他 pods 部署到管理节点上,需要去除管理节点的 Taint 标记:kubectl taint nodes --all node-role.kubernetes.io/master-

远程连接集群

kubectl 和集群进行交互的信息和凭证全部保存在 kubeconfig 文件中,如果要从其他机器上连接集群,只需要把 kubeconfig 文件放到本地,参考文档 Controlling your cluster from machines other than the control-plane node

记得在本地绑定 DNS。

记得打开服务器的 6443 端口。

Kubernetes Dashboard

最后安装一个 Kubernetes Dashboard,可视化地看一看集群状态。

当前 Kubernetes Dashboard 有 1 和 2 两个主版本,区别很大,我们安装 2 版本:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta6/aio/deploy/recommended.yaml

安装好之后,在本地运行 kube proxy:

kubectl proxy

在集群外使用 kubectl 命令,都需要注意是否需要指定 --kubeconfig 文件。

然后访问 http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

Kubernetes Dashboard 需要校验权限才能访问,可以参考 REFERENCE 中的两篇文章,但在 2 版本中,Kubernetes Dashboard 提高了安全等级,默认不开放任何权限,所以需要根据 Creating sample user 创建用户才可以访问。

需要注意的是根据以上文章创建的用户是拥有所有权限的,投入生产环境时要注意。

这样就可以用 token 方式进入 Kubernetes Dashboard 管理页面啦。

REFERENCE