# 简介
Kubernetes 是什么,Kubernetes 是一个全新的基于容器技术的分布式架构解决方案,是 Google 开源的一个容器集群管理系统。说白了,就是一个管理容器的组件。
# 事前准备
在部署前,我们要需要知道,在 Kubernetes 中,一般包含一个 Master 节点和多个 Node 节点。一个节点可以看作是一个宿主机,虚拟机。
因此我们在安装前先考虑下我们的集群规模。
这里我是部署了一个 master 和一个 work node。所以我需要准备两台虚拟机。然后就可以准备开始安装了。
(PS:这里我虚拟机有一份是直接 copy 过来的,导致这两个虚拟机的网卡 mac 地址是一致的,因此如果你也是这么做的,请在 vmware 中删除掉一台机子的网卡,再重新添加,务必保证它们的 mac 地址不相同。)
而安装中,我大致分为通用安装和 master 安装,通用安装就是无论是什么定位的虚拟机上都需要安装的,而 master 安装则是只在 master 节点上执行的操作。
以下是 Ubuntu 18.04 下的 Kubernetes 环境搭建,其他系统大同小异。
# 通用安装 (master 和 work node 都要执行的操作)
# 设置静态 ip
在 vmware 虚拟机中,如果你使用的是 nat 模式的话,设置静态 ip 是无法出网的。
所以这里推荐使用桥接模式
vim /etc/netplan/xxxx #修改配置 | |
netplan apply #应用设置 |
如果非要用 nat 模式的话也不是不行,不过需要做好在你重启机子后 vmware 分配给你虚拟机的 ip 变了的准备。
nat 模式的话,就不需要设置静态 ip 了,但是如果重启后发现虚拟机的 ip 变了的话,我们就得手动给它换 ip。
ifconfig eth1 192.168.1.10 netmask 255.255.255.0 #修改 ip | |
netplan apply #应用设置 |
# 关闭 swap 交换分区、SElinux、防火墙
为了更好的性能,在 swap 打开的情况下,kubelet 无法正常运行。
即使安装成功了,node 重启后也会出现 kubernetes server 运行错误。
swapoff -a #临时关闭,永久关闭是修改 /etc/fstab,注释掉 swap 那行(一劳永逸) | |
ufw disable #关闭防火墙 | |
setenforce 0 #临时关闭,永久关闭是修改 /etc/selinux/config 文件将 SELINUX=enforcing 改为 SELINUX=disabled |
# 添加 kubernetes 源和信任密钥
这里选择阿里源
vim /etc/apt/sources.list.d/kubernetes.list | |
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main | |
apt-get update #此时会报错,因为我们添加了一个自定义源,但没把它加到信任列表 |
gpg --keyserver keyserver.ubuntu.com --recv-keys FEEA9169307EA071 #这里需要改最后的 publickey 为报错中的 key,然后再 apt-get update 就可以了 | |
gpg --export --armor FEEA9169307EA071|sudo apt-key add - | |
apt-get update |
# 下载相关组件
apt-get install -y kubeadm kubelet kubectl | |
apt-mark hold kubelet kubeadm kubectl //hold主这些软件,使它们不自动更新 | |
apt-get install -y docker.io | |
systemctl start docker | |
systemctl enable docker |
配置 docker 加速源
vim /etc/docker/daemon.json #文件默认不存在 |
{ | |
"registry-mirrors": [ | |
"https://hub-mirror.c.163.com", | |
"https://reg-mirror.qiniu.com", | |
"https://registry.docker-cn.com" | |
] | |
} |
# docker 修改配置(不可少,否则会在 init 的时候爆错)
由于 kubelet 的 cgroup driver 是 systemd,docker 的 cgroup driver 是 cgroupfs,两者不一致导致 kubelet 启动失败。所以需要修改其中一个配置,让它们一致即可。这里我修改 docker 的
vim /etc/docker/daemon.json #添加 "exec-opts": ["native.cgroupdriver=systemd"] | |
systemctl daemon-reload | |
systemctl restart docker |
# 修改主机名与其他配置
为了更好区分实例的作用,推荐根据规划统一改名。
hostnamectl set-hostname <name> #退出当前用户即刻生效 | |
apt-get install -y apt-transport-https | |
vim /etc/systemd/resolved.conf #配置 dns 114.114.114.114 |
# master 节点安装(只在 master 节点上进行的操作)
# 下载 k8s 的各个组件
因为 k8s 的这些组件的镜像官方源被墙了,所以我们需要先从阿里云给 pull 下来,然后改标签。
kubeadm config images list #获取以上组件镜像最新版本 |
使用下述命令,从阿里源 pull 组件。下面的镜像应该去除 "k8s.gcr.io/" 的前缀,版本换成上面获取到的版本
images=( | |
kube-apiserver:v1.23.3 | |
kube-controller-manager:v1.23.3 | |
kube-scheduler:v1.12.3 | |
kube-proxy:v1.23.3 | |
pause:3.6 | |
etcd:3.5.1-0 | |
coredns:v1.8.6 | |
) | |
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 |
这里需要注意,我们重命名后的 docker 标签名必须和 kubeadm config images list 获取到的一致。而通过以上脚本,有一个标签不一致,我们需要进行修改。
# 初始化环境
这里初始化的时候,指定 pod 网络可以使用的 IP 地址段。尽量保证和宿主机的局域网的 CIDR 不一样
kubeadm init --pod-network-cidr=172.16.0.0/16 |
上面的命令执行成功后,会输出一条和 kubeadm join 相关的命令,后面加入 worker node 的时候要使用。没必要保存,因为这个时效只有 24h,我们可以随时用以下命令来获取。
kubeadm token create --print-join-command |
# 初始化环境的时候报错的情况(只有在上述步骤出问题的时候才需要操作)
重新初始化之前先重启服务。
kubeadm reset | |
systemctl restart kubelet |
# 配置 kubectl 命令授权信息
kubectl 需要经过 api server 认证和授权后才可以执行相应的管理操作,而初始化部署集群时会自动生成一个管理员权限的认证配置文件在 /etc/kubernetes/admin.conf。当使用 kubectl 命令时,默认通过 $HOME/.kube/config 路径下的认证文件进行认证。
其实就相当于 SSH 的公私钥了。
mkdir -p $HOME/.kube | |
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config | |
sudo chown $(id -u):$(id -g)$HOME/.kube/config |
然后当前用户就能够正常控制 master 了。
# 下载 pod 网络插件(calico 网络)
我们先不急着让 work 节点加进来。
在 k8s 中,并未涉及到网络的规划配置,所以如果我们想让 k8s 的 pod 网络互相隔离,就得引用其他组件。
Calico 是一种容器之间互通的网络方案。在虚拟化平台中,比如 OpenStack、Docker 等都需要实现 workloads 之间互连,但同时也需要对容器做隔离控制,就像在 Internet 中的服务仅开放 80 端口、公有云的多租户一样,提供隔离和管控机制。而在多数的虚拟化平台实现中,通常都使用二层隔离技术来实现容器的网络,这些二层的技术有一些弊端,比如需要依赖 VLAN、bridge 和隧道等技术,其中 bridge 带来了复杂性,vlan 隔离和 tunnel 隧道则消耗更多的资源并对物理环境有要求,随着网络规模的增大,整体会变得越加复杂。我们尝试把 Host 当作 Internet 中的路由器,同样使用 BGP 同步路由,并使用 iptables 来做安全访问策略,最终设计出了 Calico 方案。
curl -O https://docs.projectcalico.org/manifests/calico.yaml calico.yaml | |
kubectl apply -f calico.yaml | |
kubectl get pods --all-namespaces#最后,全部 runing 则是成功安装 master 节点。 |
# work node 加入集群
kubeadm join 192.168.5.174:6443 --token e6vkaj.ea9hs3vzjxhxgnsj --discovery-token-ca-cert-hash sha256:1408bd40e7b532e007a33e3a3f88bed3b7b541a79eff583c3ea344eaec65426f |
此时我们回到 master 节点查看情况,新加进来的节点状态并不是 ready,并且多了两个 pod,但一直创建失败。
kubectl get pod -n kube-system |
回到出问题的节点上,查看它的报错情况,我们发现它在尝试去官网 pull 一些镜像,那问题就很简单了,工作节点加入后,需要 pull 一些网络镜像,但因为中国被墙了。所以它 pull 失败,就报错了。(这里需要我们去 pull 两个镜像,一个是 pause 一个是 proxy)
journalctl -f
解决也很简单,我们手动 pull 就好了。
images=( | |
kube-proxy:v1.23.3 | |
pause:3.6 | |
) | |
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 |
pull 完成后,静待即可。回到 master 节点,此时一切就绪。
# 部署 dashboard
因为我们后续需要做 dashboard 的未授权实验,所以这里最好先提前布上。
# 修改配置文件(主要是为了让 dashboard 能被外部访问)
curl https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml |
下载 dashboard 搭建的 yaml,然后我们可以看到各种这个应用并未被设置成出网,只起了一个内部的 ip 和端口。
所以我们这里给它上 sever 代理出来。将这个 server 端口给它映射到宿主机,这样我们就能直接访问 dashboard 了。
PS:这里我给设置成了 8443,但是默认情况下 nodeport 是不允许分配到这个端口的,需要修改 api-server 中的配置文中的 --service-node-port-range=8000-10000
vim /etc/kubernetes/manifests/kube-apiserver.yaml | |
systemctl daemon-reload | |
systemctl restart kubelet |
# 提前下载国内镜像(避免 pull 官方镜像浪费时间)
查看配置文件中,下载的镜像名和版本。
images=( | |
metrics-scraper:v1.0.7 | |
dashboard:v2.4.0 | |
) | |
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 kubernetesui/$imageName | |
docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName | |
done |
# 安装部署
kubectl create -f recommendef.yaml |