使用 kubeadm 构建 kubernetes 集群.md

1,800 阅读3分钟

kubeadm 简介

Kubeadm 是一种工具,旨在为创建 Kubernetes 集群提供最佳实践“快速路径”。

它执行必要的操作,以用户友好的方式启动和运行最低可行,安全的群集。

Kubeadm 的范围仅限于本地节点文件系统和 Kubernetes API,它旨在成为更高级别工具的可组合构建块。

环境

主机名 IP地址 CPU 内存(G) 备注
k8s1 172.16.10.3 4 8 master节点
k8s2 172.16.10.4 4 8 master节点
k8s3 172.16.10.22 4 8 master节点
k8s4 172.16.10.20 4 8 worker节点
k8s5 172.16.10.19 4 8 worker节点
k8s6 172.16.10.21 4 8 worker节点

添加hosts

cat >> /etc/hosts <<EOF
172.16.10.3    k8s1
172.16.10.4    k8s2
172.16.10.22   k8s3
172.16.10.20  k8s4
172.16.10.19  k8s5
172.16.10.21  k8s6
EOF

检查服务器至少满足下面的条件:

  1. 每个节点的唯一主机名,MAC地址和product_uuid

  2. 防火墙放行应用端口

  3. 禁用交换分区

验证MAC地址和product_uuid对于每个节点都是唯一的

  • 可以使用命令ip link 或 ifconfig -a 获取网络接口的MAC地址

  • 可以使用下面命令检查product_uuid

    sudo cat /sys/class/dmi/id/product_uuid
    

关闭 SELinux 和 Firewalld

setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
iptables -P FORWARD ACCEPT

加载模块

modprobe br_netfilter
lsmod | grep br_netfilter

内核优化

cat <<EOF >  /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

安装容器运行时

自v1.6.0起,Kubernetes默认启用了CRI (Container Runtime Interface) 。

从v1.14.0开始,kubeadm将尝试通过扫描众所周知的套接字列表来自动检测Linux节点上的容器运行时。 可以在下表中找到所使用的可检测运行时和套接字路径。

Runtime Domain Socket
Docker /var/run/docker.sock
containerd /run/containerd/containerd.sock
CRI-O /var/run/crio/crio.sock

如果同时检测到Docker和containerd,则Docker优先。

因为Docker 18.09附带了containerd,两者都是可检测的。

如果检测到任何其他两个或更多运行时,kubeadm将退出并显示相应的错误消息。

如果选择的容器运行时是Docker,则通过内置的dockershimCRI实现使用它 kubelet。

安装最新稳定版的 docker-ce

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

创建 daemon.json

mkdir -p /etc/docker
cat > daemon.json <<EOF
{
  "registry-mirrors": ["http://f1361db2.m.daocloud.io"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
EOF

systemctl restart docker

安装 kubeadm,kubelet 和 kubectl

使用阿里云的源,安装kubeadm软件等

worker节点可以不安装kubectl

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum install -y kubelet-1.14.2 kubeadm-1.14.2 kubectl-1.14.2
systemctl enable kubelet

下载镜像

使用如下的命令打印出需要的镜像

$ kubeadm config images list
k8s.gcr.io/kube-apiserver:v1.14.2
k8s.gcr.io/kube-controller-manager:v1.14.2
k8s.gcr.io/kube-scheduler:v1.14.2
k8s.gcr.io/kube-proxy:v1.14.2
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.3.10
k8s.gcr.io/coredns:1.3.1

gcr.io 域名在大陆不可访问,我们使用如下的脚本下载镜像

Container Registry Proxy

#!/bin/bash

set -o errexit
set -o nounset

KUBE_VERSION=v1.14.2
KUBE_PAUSE_VERSION=3.1
ETCD_VERSION=3.3.10
DNS_VERSION=1.3.1

GCR_URL=k8s.gcr.io
HUB_URL=gcr.azk8s.cn/google_containers

images=("kube-apiserver:${KUBE_VERSION}" "kube-controller-manager:${KUBE_VERSION}" "kube-scheduler:${KUBE_VERSION}" "kube-proxy:${KUBE_VERSION}" "pause:${KUBE_PAUSE_VERSION}" "etcd:${ETCD_VERSION}" "coredns:${DNS_VERSION}")

for imageName in ${images[@]} ; do
  docker pull $HUB_URL/$imageName
  docker tag  $HUB_URL/$imageName $GCR_URL/$imageName
  docker rmi  $HUB_URL/$imageName
done

高可用拓扑

可以设置如下两种HA 集群

  • 使用堆叠的控制平面节点,其中etcd节点与控制平面节点共存
  • 使用外部etcd节点,etcd在控制平面的不同节点上运行

Stacked etcd topology

每个控制平面节点运行的一个kube-apiserver,kube-scheduler和kube-controller-manager实例。

kube-apiserver使用负载均衡器暴露于工作节点。

每个控制平面节点创建一个本地etcd成员,该etcd成员仅与该节点的kube-apiserver通信。

这同样适用于本地kube-controller-manager 和kube-scheduler实例。

该拓扑将控制平面和etcd成员耦合在相同节点上。设置比具有外部etcd节点的集群更简单,并且更易于管理复制。

但是,堆叠集群存在耦合失败的风险。如果一个节点发生故障,则etcd成员和控制平面实例都将丢失,并且冗余会受到影响。您可以通过添加更多控制平面节点来降低此风险。

因此,您应该为HA群集运行至少三个堆叠的控制平面节点。

kubeadm-ha-topology-stacked-etcd

External etcd topology

由etcd提供的分布式数据存储集群在运行控制平面组件的节点形成的集群外部。

在外部ETCD拓扑中的每个控制平面节点运行的一个kube-apiserver,kube-scheduler和kube-controller-manager实例。

并且kube-apiserver使用负载均衡器暴露给工作节点。但是,etcd成员在不同的主机上运行,​​每个etcd主机与控制平面节点的kube-apiserver进行通信。

将控制平面和etcd成员分离。因此,它提供了HA设置,其中丢失控制平面实例或etcd成员具有较小的影响并且不像堆叠的HA拓扑那样影响集群冗余。

但是,此拓扑需要两倍于堆叠HA拓扑的主机数。具有此拓扑的HA群集至少需要三个用于控制平面节点的主机和三个用于etcd节点的主机。

kubeadm-ha-topology-external-etcd

这边机选择第一种方案: stacked etcd topology

为kube-apiserver 创建负载均衡器

创建一个负载均衡器,其名称可以解析为DNS

  • 在云环境中,您应将控制平面节点置于TCP转发负载平衡器之后。此负载均衡器将流量分配到其目标列表(master节点)中的所有健康控制平面节点。apiserver的运行状况检查是对kube-apiserver侦听的端口的TCP检查(默认值:6443)。

  • 不建议直接在云环境中使用IP地址。(实验环境下,没有设置DNS解析,直接使用IP代替)

  • 负载均衡器必须能够与apiserver端口上的所有控制平面节点通信。它还必须允许其侦听端口上的传入流量。

  • HAProxy可用作负载均衡器。

  • 确保负载均衡器的地址始终与kubeadm的地址匹配ControlPlaneEndpoint。

京东云内网负载均衡监听配置截图:

slb-lister
virtual-server-group

如果没有SLB,也可以使用Haproxy

Haproxy配置文件见 haproxy.cfg

堆叠控制平面和etcd节点

第一个控制平面节点的步骤

  1. 在第一个控制平面节点上,创建一个名为的配置文件kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: 1.14.2
controlPlaneEndpoint: "172.16.10.5:6443"
networking:
  serviceSubnet: "10.96.0.0/12"
  podSubnet: "10.244.0.0/16"
  dnsDomain: "cluster.local"
  • kubernetesVersion应该设置为使用的Kubernetes版本。这边使用1.14.2

  • controlPlaneEndpoint 应匹配负载均衡器的地址或DNS和端口。

  • networking 设置CNI 网络插件需要的CIDR

  1. 初始化控制平面:
kubeadm init --config=kubeadm-config.yaml --experimental-upload-certs
  • --experimental-upload-certs标志用于将应在所有控制平面实例之间共享的证书上载到群集。相反,如果您希望手动或使用自动化工具跨控制平面节点复制证书,请删除此标志并参考手动证书分发部分。

命令执行完成之后,输出类似下面:

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 the control-plane node running the following command on each as root:

  kubeadm join 172.16.10.5:6443 --token o8d1ee.tzswy9o52p6m00i4 \
    --discovery-token-ca-cert-hash sha256:56047868636349ca477d271496689f5d83055d8ff3e2cc594b5a419501962d18 \
    --experimental-control-plane --certificate-key d19b85d6692cde12ad8a85fd882b45293c2cda35b32edb2ad217192c8b836821

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --experimental-upload-certs" to reload certs afterward.

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

kubeadm join 172.16.10.5:6443 --token o8d1ee.tzswy9o52p6m00i4 \
    --discovery-token-ca-cert-hash sha256:56047868636349ca477d271496689f5d83055d8ff3e2cc594b5a419501962d18

3.安装flannel网络插件

flannel 文档

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.11.0/Documentation/kube-flannel.yml

安装其余控制平面节点

 kubeadm join 172.16.10.5:6443 --token o8d1ee.tzswy9o52p6m00i4 \
    --discovery-token-ca-cert-hash sha256:56047868636349ca477d271496689f5d83055d8ff3e2cc594b5a419501962d18 \
    --experimental-control-plane --certificate-key d19b85d6692cde12ad8a85fd882b45293c2cda35b32edb2ad217192c8b836821

安装worker节点

kubeadm join 172.16.10.5:6443 --token o8d1ee.tzswy9o52p6m00i4 \
    --discovery-token-ca-cert-hash sha256:56047868636349ca477d271496689f5d83055d8ff3e2cc594b5a419501962d18

确认节点已全部安装完成

$ kubectl get nodes
NAME   STATUS   ROLES    AGE     VERSION
k8s1   Ready    master   2d13h   v1.14.2
k8s2   Ready    master   2d13h   v1.14.2
k8s3   Ready    master   2d13h   v1.14.2
k8s4   Ready    <none>   2d13h   v1.14.2
k8s5   Ready    <none>   2d13h   v1.14.2
k8s6   Ready    <none>   2d13h   v1.14.2
$ kubectl get pod -n kube-system
NAME                           READY   STATUS    RESTARTS   AGE
coredns-fb8b8dccf-g4lf5        1/1     Running   0          2d13h
coredns-fb8b8dccf-z4rrq        1/1     Running   0          2d13h
etcd-k8s1                      1/1     Running   0          2d13h
etcd-k8s2                      1/1     Running   0          2d13h
etcd-k8s3                      1/1     Running   0          2d13h
kube-apiserver-k8s1            1/1     Running   0          2d13h
kube-apiserver-k8s2            1/1     Running   0          2d13h
kube-apiserver-k8s3            1/1     Running   1          2d13h
kube-controller-manager-k8s1   1/1     Running   1          2d13h
kube-controller-manager-k8s2   1/1     Running   0          2d13h
kube-controller-manager-k8s3   1/1     Running   0          2d13h
kube-flannel-ds-amd64-22j5p    1/1     Running   0          2d13h
kube-flannel-ds-amd64-2gnxf    1/1     Running   0          2d13h
kube-flannel-ds-amd64-bbttc    1/1     Running   0          2d13h
kube-flannel-ds-amd64-st9xk    1/1     Running   0          2d13h
kube-flannel-ds-amd64-v5bjs    1/1     Running   0          2d13h
kube-flannel-ds-amd64-wqsrq    1/1     Running   0          2d13h
kube-proxy-5wxg5               1/1     Running   0          2d13h
kube-proxy-6j5kj               1/1     Running   0          2d13h
kube-proxy-9f9sm               1/1     Running   0          2d13h
kube-proxy-j2c4p               1/1     Running   0          2d13h
kube-proxy-lhtjv               1/1     Running   0          2d13h
kube-proxy-rxbwj               1/1     Running   0          2d13h
kube-scheduler-k8s1            1/1     Running   1          2d13h
kube-scheduler-k8s2            1/1     Running   0          2d13h
kube-scheduler-k8s3            1/1     Running   0          2d13h