准备开始
- 一台至少有 8G 内存的电脑
- 已安装虚拟机,比如
VirtualBox - 已下载好
Ubuntu镜像文件,比如可以从清华镜像站下载,版本最好在 16.04 以上
虚拟机安装
虚拟机配置
这里并不赘述如何安装虚拟机,不过请确保给虚拟机分配如下配置
- 至少 2G 内存,过少会影响运行
- 至少 2 核 CPU,必须
- 网络连接选择
桥接网卡,界面选择你宿主机当前活跃的网卡
安装系统
系统配置
软件源设置国内镜像
两种方式选择其一
- 打开
软件与更新,选择国内一个速度比较好的源 - 手动修改
/etc/apt/sources.list,参考如 mirrors.tuna.tsinghua.edu.cn/help/ubuntu…
设置一个可用的 DNS 服务器
安装 Docker
安装
参考 yeasy.gitbook.io/docker_prac…
或者 k8s 的文档 kubernetes.io/zh/docs/set…
建议按照 k8s 的文档安装,但是安装时可以按第一个文档替换成国内 GPG 密钥和 apt 源。
做镜像加速
编辑 vim /etc/docker/daemon.json ,添加如下内容
{
"registry-mirrors":
[
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
重启 docker 服务
sudo systemctl daemon-reload
sudo systemctl restart docker
安装 ssh 服务
为了能够从宿主机 ssh 访问到虚拟机,我们需要安装 ssh 服务
sudo apt install openssh-server && \
sudo systemctl enable ssh && \
sudo systemctl restart ssh
宿主机从外部访问时可以利用 ssh-copy-id username@ip-your-host 把密钥保存到虚拟机,就不用每次利用密码访问了。具体操作可以参考之前的一篇文章 >>> 。
关闭防火墙
本机的学习环境为了方便可以直接关闭,而生产环境则应该按需打开相应端口。
sudo ufw disable
为安装k8s进行的设定
确保 iptables 工具不使用 nftables 后端
如果您系统的 iptables 工具使用 nftables 后端,则需要把 iptables 工具切换到“旧版”模式来避免这些问题。 默认情况下,至少在 Debian 10 (Buster)、Ubuntu 19.04、Fedora 29 和较新的发行版本中会出现这种问题。RHEL 8 不支持切换到旧版本模式,因此与当前的 kubeadm 软件包不兼容。
update-alternatives --set iptables /usr/sbin/iptables-legacy
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
update-alternatives --set arptables /usr/sbin/arptables-legacy
update-alternatives --set ebtables /usr/sbin/ebtables-legacy
解释说明参考 k8s 官方文档
禁用交换分区
查看是否已禁用交换分区
第一个办法 free -m,看到 swap 一行 都是 0
第二个办法 swapon -v ,输出空白则已关闭
禁用方法
编辑 vim/etc/fstab 文件,注释掉swap was on /dev/sda5 during installation 下面的配置,即截图中光标所在行
复制多台虚拟机
现在我们已经把集群的控制面板的机器安装好了环境,下一步看你宿主机的配置,想搭配多少 worker,就多复制几台。我们使用复制功能,也是想减少工作量,因为如果单独配置需要大量手动工作。
复制操作如下
- 停止现有虚拟机
- 在 VirtualBox 等面板的虚拟机列表中选择刚刚我们配置好的机器,右键 选择 复制
- 设置新的虚拟机,留意 MAC 地址要设定重新生成
虚拟机准备效果
安装集群前的再检查
确保每个节点上 MAC 地址和 product_uuid 的唯一性
您可以使用命令 ip link 或 ifconfig -a 来获取网络接口的 MAC 地址
可以使用 sudo cat /sys/class/dmi/id/product_uuid 命令对 product_uuid 校验
一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。Kubernetes 使用这些值来唯一确定集群中的节点。 如果这些值在每个节点上不唯一,可能会导致安装失败。
检查网络
利用 ping 或者其他工具,检查以上各个节点的连通性,如果不通,则应当考虑 网络连接方式、防火墙或者其他。
安装控制面板
注意
集群安装命令,我们均以 root 用户执行
sudo -i
安装
apt-get update && apt-get install -y apt-transport-https curl
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl # 默认安装最新版本
apt-mark hold kubelet kubeadm kubectl
systemctl daemon-reload
systemctl restart kubelet
如果需要安装指定版本的组件可以指定版本,如sudo apt-get install -y kubeadm=1.18.8-00 kubelet=1.18.8-00 kubectl=1.18.8-00
确定软件
kubeadm version
初始化集群
在初始化集群之前,确定你想安装的的 网络组件,如果不知道选择哪个,我们以 flannel 示例。因为有的 网络组件 要求在初始化的时候需要指定 pod 的 cidr。如 官方文档的说明 >>> v1-17.docs.kubernetes.io/docs/setup/…
补充:后期如果要测试 NetworkPolicy,因为这个功能只有部分网络组件支持,如 Calico Cilium Kube-router Romana Weave,所以请自行选择。
因为 kubeadm 安装的控制面板的 apiserver 等各个组件都是以静态 pod 的形式运行的,所以在初始化的时候会拉取镜像,然后启动 docker,为了加快初始化的过程,我们可以先把需要的镜像拉取下来,并且一定要指定镜像仓库,因为默认的是谷歌的,是访问不了的。
预先拉取镜像
kubeadm config images pull --image-repository=registry.aliyuncs.com/google_containers
初始化
kubeadm init --pod-network-cidr=10.244.0.0/16 \
--image-repository=registry.aliyuncs.com/google_containers
执行过程如下
root@vb-n1:~# kubeadm init --pod-network-cidr=10.244.0.0/16 \
> --image-repository=registry.aliyuncs.com/google_containers
I0924 02:27:10.520223 12818 version.go:252] remote version is much newer: v1.19.2; falling back to: stable-1.18
W0924 02:27:15.428893 12818 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[init] Using Kubernetes version: v1.18.9
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [vb-n1 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.43.72]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [vb-n1 localhost] and IPs [192.168.43.72 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [vb-n1 localhost] and IPs [192.168.43.72 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
W0924 02:36:50.592219 12818 manifests.go:225] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[control-plane] Creating static Pod manifest for "kube-scheduler"
W0924 02:36:50.593625 12818 manifests.go:225] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 24.504562 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.18" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node vb-n1 as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node vb-n1 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: 2dsvjn.icq3o9bbenit60kg
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
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
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:
kubeadm join 192.168.43.72:6443 --token 2dsvjn.icq3o9bbenit60kg \
--discovery-token-ca-cert-hash sha256:43a6c576e9efe1f581369ca443bba0a271b9a898a5a94a52730c4e03d617d88d
上面的输出提示,重要信息有两块
1 是集群的相关配置文件要让你将管理集群的用户能够访问到
# 对于非 root 用户管理集群,需要
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 对于 root 用户
export KUBECONFIG=/etc/kubernetes/admin.conf
2 指明了其他节点加入集群的方法
因为要验证身份,token 参数是有有效期的,一般是 23 小时,不过过期了也没关系,官方文档也给出了重新生成的方法。
不需要执行,只做示例
kubeadm join 192.168.43.72:6443 --token 2dsvjn.icq3o9bbenit60kg \
--discovery-token-ca-cert-hash sha256:43a6c576e9efe1f581369ca443bba0a271b9a898a5a94a52730c4e03d617d88d
确定集群状态
# 可以用如下命令确定集群安装情况,可以看到我们的第一个节点是 Ready 的状态
kubectl get nodes
kubectl cluster-info
安装工作节点
注意
以下安装步骤操作都是以 root 用户
sudo -i
安装
apt-get update && apt-get install -y apt-transport-https curl
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm # 默认安装最新版本
apt-mark hold kubelet kubeadm
systemctl daemon-reload
systemctl restart kubelet
加入集群
kubeadm join 192.168.43.72:6443 --token 2dsvjn.icq3o9bbenit60kg \
--discovery-token-ca-cert-hash sha256:43a6c576e9efe1f581369ca443bba0a271b9a898a5a94a52730c4e03d617d88d
最后会有如下输出提示
查看已加入的节点和整个集群状态
在控制面板节点执行如下
kubectl get nodes
安装网络组件
现在工作节点已经在集群中注册成功了,但是工作节点和集群还不能进行正常连通。需要安装一款网络组件,刚刚我们在初始化集群指定了一个 pod cidr,我们选择的是 flannel ,需要在 master 控制面板中执行如下
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.12.0/Documentation/kube-flannel.yml
大功告成
这时我们再来执行,就会发现工作节点已经准备就绪了
kubectl get nodes
小试牛刀
我们现在来创建一个 pod 试试,我们看到几秒钟就创建好了这个 pod
kubectl run nginx --image=nginx --port=80
你也可以尝试 kubectl describe pod nginx | grep IP 找到这个 pod 在集群中的 IP,然后尝试 curl 访问