前言
本文介绍如何在ubuntu
上部署k8s
集群,大致可以分为如下几个步骤:
- 修改
ubuntu
配置 - 安装
docker
- 安装
kubeadm
、kubectl
以及kubelet
- 初始化
master
节点 - 将
slave
节点加入网络
如果你对上面的某些名字感到陌生,没关系,下文会一一进行讲解,如果你想先了解一下 docker 和 k8s,可以参考 10分钟看懂Docker和K8S。好了,在正式开始之前,首先看一下我们都有哪些服务器,如果你对如何组建如下虚拟机网络感兴趣的话,可以参考 virtualbox 虚拟机组网:
VMware 中使用Ubuntu 20.04 版本的镜像安装一个虚拟机,执行如下操作:
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.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 install openssh-server
sudo apt install net-tools
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
sudo systemctl enable ssh
sudo systemctl enable docker
克隆两台虚拟机,然后按图中的四步修改虚拟机的MAC地址
4.png
主机名 | 主机ip | 版本 | CPU | 内存 |
---|---|---|---|---|
master1 | 192.168.56.11 | Ubuntu server 18.04 | 2核 | 1G |
worker1 | 192.168.56.21 | Ubuntu server 18.04 | 2核 | 1G |
因为k8s
分为管理节点和工作节点,所以我们将要 在master1
上部署管理节点,在worker1
上部署工作节点。如果想了解如何创建这两个节点,可以参考 virtualbox 虚拟机组网 。服务器配置上,k8s 要求 CPU 最低为 2 核,不然在安装过程中会报错,虽然这个错误可以避免,但是为了稳定起见还是把虚拟机的配置成它想要的,至于内存 k8s 没有硬性要求,所以我就按我电脑的性能来分配了。
注意,本文的 docker、k8s 等软件安装均未指定具体版本,在本文完成时2019/6/27
,下载到的版本如下,如有特殊版本需要请自行指定版本。
软件名 | 版本 |
---|---|
docker | 18.09.5 |
kubectl | 1.15.0-00 amd64 |
kubeadm | 1.15.0-00 amd64 |
kubelet | 1.15.0-00 amd64 |
一. 修改 ubuntu 配置
首先,k8s 要求我们的 ubuntu 进行一些符合它要求的配置。很简单,包括以下两步:关闭 Swap
内存 以及 配置免密登录,这一步两台主机都需要进行配置。
关闭 swap 内存
这个swap
其实可以类比成 windows 上的虚拟内存,它可以让服务器在内存吃满的情况下可以保持低效运行,而不是直接卡死。但是 k8s 的较新版本都要求关闭swap
。所以咱们直接动手,修改/etc/fstab
文件:
sudo vi /etc/fstab
你应该可以看到如下内容,把第二条用#
注释掉就好了,注意第一条别注释了,不然重启之后系统有可能会报file system read-only
错误。
UUID=e2048966-750b-4795-a9a2-7b477d6681bf / ext4 errors=remount-ro 0 1
# /dev/fd0 /media/floppy0 auto rw,user,noauto,exec,utf8 0 0
然后输入reboot
重启即可,重启后使用top
命令查看任务管理器,如果看到如下KiB Swap
后均为 0
就说明关闭成功了。
上面说的是永久关闭swap
内存,其实也可以暂时关闭,使用swapoff -a
命令即可,效果会在重启后消失。
配置免密登录
k8s 要求 管理节点可以直接免密登录工作节点 的原因是:在集群搭建完成后,管理节点的 kubelet 需要登陆工作节点进行操作。而至于怎么操作很简单,这里就不详提了,可以参见文章 virtualbox 虚拟机组网 的最后一个章节 免密钥登录 。
设置host-name
注意集群内的机器hostname不能重复,要不然节点加入的时候会报错:
error execution phase kubelet-start: a Node with name "ubuntu" and status "Ready" already exists in the cluster. You must delete the existing Node or change the name of this new joining Node
设置命令
# 设置hostname master 或者 worker1 或者 worker2
hostnamectl set-hostname master/worker1/worker2
二. 安装 docker
docker 是 k8s 的基础,在安装完成之后也需要修改一些配置来适配 k8s ,所以本章分为 docker 的安装 与 docker 的配置 两部分。如果你已经安装并使用了一段时间的 docker 了话,建议使用docker -v
查看已安装的 docker 版本,并在 k8s 官网上查询适合该版本的 k8s 进行安装。这一步两台主机都需要进行安装。
docker 的安装
docker 在 ubuntu 的安装上真是再简单不过了,执行如下命令即可,在安装之前请记得把镜像源切换到国内。
sudo apt install docker.io
等安装完成之后使用docker -v
来验证 docker是否可用。
docker 的配置
安装完成之后需要进行一些配置,包括 切换docker下载源为国内镜像站 以及 修改cgroups。
这个cgroups
是啥呢,你可以把它理解成一个进程隔离工具,docker
就是用它来实现容器的隔离的。docker 默认使用的是cgroupfs
,而 k8s 也用到了一个进程隔离工具systemd
,如果使用两个隔离组的话可能会引起异常,所以我们要把 docker 的也改成systemd
。
这两者都是在/etc/docker/daemon.json
里修改的,所以我们一起配置了就好了,首先执行下述命令编辑daemon.json
:
sudo vi /etc/docker/daemon.json
打开后输入以下内容:
{
"registry-mirrors": [
"https://dockerhub.azk8s.cn",
"https://reg-mirror.qiniu.com",
"https://quay-mirror.qiniu.com"
],
"exec-opts": [ "native.cgroupdriver=systemd" ]
}
然后:wq
保存后重启 docker:
sudo systemctl daemon-reload
sudo systemctl restart docker
然后就可以通过docker info | grep Cgroup
来查看修改后的 docker cgroup 状态,发现变为systemd
即为修改成功。
三. 安装 k8s
安装完了 docker 就可以下载 k8s 的三个主要组件kubelet
、kubeadm
以及kubectl
了。这一步两台主机都需要进行安装。先来简单介绍一下这三者:
-
kubelet
: k8s 的核心服务 -
kubeadm
: 这个是用于快速安装 k8s 的一个集成工具,我们在master1
和worker1
上的 k8s 部署都将使用它来完成。 -
kubectl
: k8s 的命令行工具,部署完成之后后续的操作都要用它来执行
其实这三个的下载很简单,直接用apt-get
就好了,但是因为某些原因,它们的下载地址不存在了。所以我们需要用国内的镜像站来下载,也很简单,依次执行下面五条命令即可:
# 使得 apt 支持 ssl 传输
apt-get update && apt-get install -y apt-transport-https
# 下载 gpg 密钥 这个需要root用户否则会报错
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
# 添加 k8s 镜像源 这个需要root用户否则会报错
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
# 更新源列表
apt-get update
# 下载 kubectl,kubeadm以及 kubelet
apt-get install -y kubelet kubeadm kubectl
直接在/etc/apt/sources.list
里添加https://mirrors.aliyun.com/kubernetes/apt/
是不行的,因为这个阿里镜像站使用的ssl
进行传输的,所以要先安装apt-transport-https
并下载镜像站的密钥才可以进行下载。
四. 安装 master 节点
下载完成后就要迎来重头戏了,初始化master
节点,这一章节只需要在管理节点上配置即可,大致可以分为如下几步:
- 初始化
master
节点 - 部署
flannel
网络 - 配置
kubectl
工具
初始化 master 节点
使用kubeadm
的init
命令就可以轻松的完成初始化,不过需要携带几个参数,如下。先不要直接复制执行,将赋值给--apiserver-advertise-address
参数的 ip 地址修改为自己的master
主机地址,然后再执行。
# 先拉取coredns的镜像否则下一步会失败
docker pull coredns/coredns:1.8.4
docker tag coredns/coredns:1.8.4 registry.aliyuncs.com/google_containers/coredns:v1.8.4
# 初始化
kubeadm init \
--apiserver-advertise-address=192.168.196.141 \
--image-repository registry.aliyuncs.com/google_containers \
--pod-network-cidr=10.244.0.0/16
这里介绍一下一些常用参数的含义:
-
--apiserver-advertise-address
: k8s 中的主要服务apiserver
的部署地址,填自己的管理节点 ip -
--image-repository
: 拉取的 docker 镜像源,因为初始化的时候kubeadm
会去拉 k8s 的很多组件来进行部署,所以需要指定国内镜像源,下不然会拉取不到镜像。 -
--pod-network-cidr
: 这个是 k8s 采用的节点网络,因为我们将要使用flannel
作为 k8s 的网络,所以这里填10.244.0.0/16
就好 -
--kubernetes-version
: 这个是用来指定你要部署的 k8s 版本的,一般不用填,不过如果初始化过程中出现了因为版本不对导致的安装错误的话,可以用这个参数手动指定。 -
--ignore-preflight-errors
: 忽略初始化时遇到的错误,比如说我想忽略 cpu 数量不够 2 核引起的错误,就可以用--ignore-preflight-errors=CpuNum
。错误名称在初始化错误时会给出来。
当你看到如下字样是,就说明初始化成功了,请把最后那行以kubeadm join
开头的命令复制下来,之后安装工作节点时要用到的,如果你不慎遗失了该命令,可以在master
节点上使用kubeadm token create --print-join-command
命令来重新生成一条。
Your Kubernetes master 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/
You can now join any number of machines by running the following on each node
as root:
kubeadm join 192.168.56.11:6443 --token wbryr0.am1n476fgjsno6wa --discovery-token-ca-cert-hash sha256:7640582747efefe7c2d537655e428faa6275dbaff631de37822eb8fd4c054807
如果在初始化过程中出现了任何Error
导致初始化终止了,使用kubeadm reset
重置之后再重新进行初始化。
完整输出:
root@ubuntu:/home/mico# kubeadm init --apiserver-advertise-address=192.168.196.141 --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr=10.244.0.0/16
[init] Using Kubernetes version: v1.22.1
[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'
[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 [kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local ubuntu] and IPs [10.96.0.1 192.168.196.141]
[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 [localhost ubuntu] and IPs [192.168.196.141 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost ubuntu] and IPs [192.168.196.141 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
[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
[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"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[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 20.516007 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.22" 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 ubuntu as control-plane by adding the labels: [node-role.kubernetes.io/master(deprecated) node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node ubuntu as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: i9rpmm.8jqs342cmyj1hfwg
[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
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:
kubeadm join 192.168.196.141:6443 --token i9rpmm.8jqs342cmyj1hfwg \
--discovery-token-ca-cert-hash sha256:95f83d494d4d484945f8017a70bf2f7c6b238c8ca844d431facc4b19dc4105f2
配置 kubectl 工具
这一步就比较简单了,直接执行如下命令即可:
mkdir -p /root/.kube && \
cp /etc/kubernetes/admin.conf /root/.kube/config
执行完成后并不会刷新出什么信息,可以通过下面两条命令测试 kubectl
是否可用:
# 查看已加入的节点
kubectl get nodes
# 查看集群状态
kubectl get cs
部署 flannel 网络
flannel
是什么?它是一个专门为 k8s 设置的网络规划服务,可以让集群中的不同节点主机创建的 docker 容器都具有全集群唯一的虚拟IP地址。想要部署flannel
的话直接执行下述命令即可:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml
报错:
root@ubuntu:/home/mico# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml
serviceaccount/flannel unchanged
configmap/kube-flannel-cfg unchanged
unable to recognize "https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml": no matches for kind "ClusterRole" in version "rbac.authorization.k8s.io/v1beta1"
unable to recognize "https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml": no matches for kind "ClusterRoleBinding" in version "rbac.authorization.k8s.io/v1beta1"
unable to recognize "https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml": no matches for kind "DaemonSet" in version "extensions/v1beta1"
unable to recognize "https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml": no matches for kind "DaemonSet" in version "extensions/v1beta1"
unable to recognize "https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml": no matches for kind "DaemonSet" in version "extensions/v1beta1"
unable to recognize "https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml": no matches for kind "DaemonSet" in version "extensions/v1beta1"
unable to recognize "https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml": no matches for kind "DaemonSet" in version "extensions/v1beta1"
换地址
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/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 unchanged
configmap/kube-flannel-cfg configured
daemonset.apps/kube-flannel-ds created
输出如下内容即为安装完成:
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.extensions/kube-flannel-ds-amd64 created
daemonset.extensions/kube-flannel-ds-arm64 created
daemonset.extensions/kube-flannel-ds-arm created
daemonset.extensions/kube-flannel-ds-ppc64le created
daemonset.extensions/kube-flannel-ds-s390x created
至此,k8s 管理节点部署完成。
五. 将 slave 节点加入网络
首先需要重复步骤 1 ~ 3 来安装 docker 、k8s 以及修改服务器配置,之后执行从步骤 4 中保存的命令即可完成加入,注意,这条命令每个人的都不一样,不要直接复制执行:
kubeadm join 192.168.56.11:6443 --token wbryr0.am1n476fgjsno6wa --discovery-token-ca-cert-hash sha256:7640582747efefe7c2d537655e428faa6275dbaff631de37822eb8fd4c054807
待控制台中输出以下内容后即为加入成功:
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 master to see this node join the cluster.
随后登录master1
查看已加入节点状态,可以看到worker1
已加入,并且状态均为就绪。至此,k8s 搭建完成:
root@master1:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master1 Ready master 145m v1.15.0
worker1 Ready <none> 87m v1.15.0
默认网卡问题修复
如果你是使用virtualBox
部署的虚拟机,并且虚拟机直接无法使用网卡1的 ip 地址互相访问的话(例如组建双网卡,网卡1为 NAT 地址转换用来上网,网卡2为Host-only
,用于虚拟机之间访问)。就需要执行本节的内容来修改 k8s 的默认网卡。不然会出现一些命令无法使用的问题。如果你的默认网卡可以进行虚拟机之间的相互访问,则没有该问题。
修改 kubelet 默认地址
访问kubelet
配置文件:
sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
在最后一行ExecStart
之前 添加如下内容:
Environment="KUBELET_EXTRA_ARGS=--node-ip=192.168.56.21"
重启kubelet
:
systemctl stop kubelet.service && \
systemctl daemon-reload && \
systemctl start kubelet.service
至此修改完成,更多信息详见 kubectl logs、exec、port-forward 执行失败问题解决 。
修改 flannel 的默认网卡
编辑flannel
配置文件
sudo kubectl edit daemonset kube-flannel-ds-amd64 -n kube-system
找到spec.template.spec.containers.args
字段并添加--iface=网卡名
,例如我的网卡是enp0s8
:
- args:
- --ip-masq
- --kube-subnet-mgr
# 添加到这里
- --iface=enp0s8
:wq
保存修改后输入以下内容删除所有 flannel,k8s 会自动重建:
kubectl delete pod -n kube-system -l app=flannel
至此修改完成,更多内容请见 解决k8s无法通过svc访问其他节点pod的问题 。
总结
至此你应该已经搭建好了一个完整可用的双节点 k8s 集群了。接下来你可以通过如下内容继续深入 k8s,排名分先后,推荐依次阅读:
参考
- kubeadm安装Kubernetes 1.14最佳实践
- Docker中的Cgroup Driver:Cgroupfs 与 Systemd
- Ubuntu16.04搭建Kubernetes
- Flannel介绍
- k8s 官方文档
- (k8s 部署问题解决(节点状态为 NotReady)_yrx420909的博客-CSDN博客
- k8s入门-1 在Ubuntu20.04安装步骤及问题[图文]_mb5fdb0a87e2fa1_51CTO博客
- Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0.1:10252: connect: connection refused - 云+社区 - 腾讯云 (tencent.com)
网友评论