# 简介

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   #应用设置

image-20220303144608411

如果非要用 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   #此时会报错,因为我们添加了一个自定义源,但没把它加到信任列表

image-20220303145105050

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 的

image-20220303145419530

vim /etc/docker/daemon.json #添加   "exec-opts": ["native.cgroupdriver=systemd"]
systemctl daemon-reload 
systemctl restart docker

image-20220303145506397

# 修改主机名与其他配置

为了更好区分实例的作用,推荐根据规划统一改名。

hostnamectl set-hostname <name> #退出当前用户即刻生效
apt-get install -y apt-transport-https
vim /etc/systemd/resolved.conf  #配置 dns 114.114.114.114

image-20220303152042169

# master 节点安装(只在 master 节点上进行的操作)

# 下载 k8s 的各个组件

因为 k8s 的这些组件的镜像官方源被墙了,所以我们需要先从阿里云给 pull 下来,然后改标签。

image-20220303145940181

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

image-20220303145946616

这里需要注意,我们重命名后的 docker 标签名必须和 kubeadm config images list 获取到的一致。而通过以上脚本,有一个标签不一致,我们需要进行修改。

image-20220303150121105

# 初始化环境

这里初始化的时候,指定 pod 网络可以使用的 IP 地址段。尽量保证和宿主机的局域网的 CIDR 不一样

kubeadm init  --pod-network-cidr=172.16.0.0/16

上面的命令执行成功后,会输出一条和 kubeadm join 相关的命令,后面加入 worker node 的时候要使用。没必要保存,因为这个时效只有 24h,我们可以随时用以下命令来获取。

kubeadm token create --print-join-command

image-20220303150305594

# 初始化环境的时候报错的情况(只有在上述步骤出问题的时候才需要操作)

重新初始化之前先重启服务。

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 了。

image-20220303150511119

# 下载 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 节点。

image-20220303150625607

# work node 加入集群

kubeadm join 192.168.5.174:6443 --token e6vkaj.ea9hs3vzjxhxgnsj --discovery-token-ca-cert-hash sha256:1408bd40e7b532e007a33e3a3f88bed3b7b541a79eff583c3ea344eaec65426f

image-20220303151133982

此时我们回到 master 节点查看情况,新加进来的节点状态并不是 ready,并且多了两个 pod,但一直创建失败。

kubectl get pod -n kube-system

image-20220303151141142

image-20220303151147085

回到出问题的节点上,查看它的报错情况,我们发现它在尝试去官网 pull 一些镜像,那问题就很简单了,工作节点加入后,需要 pull 一些网络镜像,但因为中国被墙了。所以它 pull 失败,就报错了。(这里需要我们去 pull 两个镜像,一个是 pause 一个是 proxy)

journalctl -f

image-20220303151217501

解决也很简单,我们手动 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 节点,此时一切就绪。

image-20220303151338949

# 部署 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

image-20220303151531598

# 提前下载国内镜像(避免 pull 官方镜像浪费时间)

查看配置文件中,下载的镜像名和版本。

image-20220303151720707

image-20220303151737155

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

image-20220303151830492

image-20220303151833354