从 logo 就可以发现,如果说 docker 的 logo 是一艘货轮,上面堆满了集装箱。那 Kubernetes 的 logo 则是舵手,指引货轮顺利航行。这也说明 Kubernetes 的用途:容器编排。
关于 Kubernetes
docker 拥有着自己的容器编排技术,docker swarm。且功能目前也比较完善,对大量节点管理也没问题。那为何还放弃 swarm 转而学习 Kubernetes,原因大致如下:
1. Kubernetes 谷歌开源,根据自己内部系统 Borg(谷歌内部使用已经长达十多年的容器编排系统) 使用 Go 语言重写。
2. 容器市场并非只有 docker,之前说过 docker 并非最佳容器方案,只是市场占有最高的容器方案。Kubernetes 能支持其它容器编排。
3. Kubernetes 拥有完善的 Devops 流程,能自动根据实际情况对业务进行扩缩容,自我修复,以及更友好的版本升级回滚等。
当然还有其它一些优势,这里挑些重点的说说。
关于 Kubernetes 集群中的两种角色:Master / Node。在 Docker Swarm 中也有对应的:Master / Worker。
和 swarm 一样,后续的所有操作都只能在 Master 上面执行,这意味着 Master 节点高可用的重要性。
在 swarm 中,用户为了便于管理,会将容器以 service 的方式进行整合,而 Kubernetes 中则使用 Pod(由一个或多个关系紧密容器集合)。
Kubernetes 本身各服务之间通信均采用 https 的方式,这就会涉及到证书问题,Kubernetes 的证书默认期限是一年,Kubernetes 期望我们每年能够更新一次版本,这样证书就能跟随着更新,但是对于生产环境而言,这显然有些不现实。至于解决方案,后续会单独提出。
所以,这就意味着如果用户一个一个的去手动安装服务会很麻烦,于是就有了后来的 kubeadm 的方式。
在管理方面,虽然目前 Kubernetes 已经能够管理各式各样的服务,但是对于有状态的服务,如数据库这类,个人还是比较推荐单独安装,原因如下:
1. 出问题比较容易排查和修复。
2. 易于维护,数据安全性,稳定性拍在第一位。
3. 这类服务几乎很少出现迭代更新的情况。
关于 Kubernetes 的各个部件:
Manager 组件说明:
1. API Server:网关,核心服务,所以服务之间通信都得通过网关分发。
2. Scheduler:调度器,将用户请求根据系统资源占用分配到合适的 Node 上面执行。
3. Controller Manager:控制器,监控集群状态和系统使用情况。
4. etcd:提供一个高性能的键值对数据库,将节点状态,服务配置等保存其中。
Node 组件说明:
1. Kubectl:和 Master 的 API Server 进行通信,接收服务端指定,并执行指令。
2. Kube-proxy:和 Manager 的 API Server 进行通信,为当前节点生成 iptables 或者 ipvs 规则,实现请求调度。关于调度实现,早期为 userspace,后改为 iptables,最后统一为 ipvs。
3. Container engine:容器引擎,这里以 docker 为例,当然不止于 docker。
其它组件(了解):
1. Kube-dns:提供 DNS 解析服务。
2. Igress Controller:提供服务外网入口。
3. Dashboard:提供 Kubernetes 的管理页面。
4. Federation:提供跨可用区的集群方案。
5. efk:提供日志收集工作。
6. Prometheus:提供业务监控。
安装准备
准备 4 台干净的虚拟机,docker 都最好不安装,因为 Kubernetes 对于 docker 版本有限制:
| 名称 | IP | 安装服务 |
|---|---|---|
| Kubernetes Manager | 192.168.200.101 | Kubernetes + flannel + docker |
| Kubernetes Node | 192.168.200.102 | Kubernetes + flannel + docker |
| Kubernetes Node | 192.168.200.103 | Kubernetes + flannel + docker |
| Doker registry harbor | 192.168.200.104 | docker + harbor |
1. 所有机器执行:系统初始化优化(注意服务器时间同步,如果服务器时间有问题会出现拉镜像报错):
# 每台机器都增加主机名解析 echo "# Kubernetes 192.168.100.101 node-01 192.168.100.102 node-02 192.168.100.103 node-03 192.168.100.104 node-04" >> /etc/hosts # 每台机器都安装依赖 yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wgetvimnet-tools git # 每台机器都关闭防火墙 systemctl stop firewalld systemctl disable firewalld # 每台机器都关闭 selinux setenforce 0 sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config # 每台机器都禁用 swap swapoff -a sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab # 内核参数调优 cat > /etc/sysctl.d/kubernetes.conf <<EOF net.bridge.bridge-nf-call-iptables=1 net.bridge.bridge-nf-call-ip6tables=1 net.ipv4.ip_forward=1 net.ipv4.tcp_tw_recycle=0 vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它 vm.overcommit_memory=1 # 不检查物理内存是否够用 vm.panic_on_oom=0 # 开启 OOM fs.inotify.max_user_instances=8192 fs.inotify.max_user_watches=1048576 fs.file-max=52706963 fs.nr_open=52706963 net.ipv6.conf.all.disable_ipv6=1 net.netfilter.nf_conntrack_max=2310720 EOF # 生效内核参数 sysctl -p /etc/sysctl.d/kubernetes.conf # 关闭不需要的服务 systemctl stop postfix systemctl disable postfix # 配置 IPVS modprobe br_netfilter echo 'modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4' >> /etc/sysconfig/modules/ipvs.modules # 生效配置 chmod 755 /etc/sysconfig/modules/ipvs.modules bash /etc/sysconfig/modules/ipvs.modules lsmod | grep -e ip_vs -e nf_conntrack_ipv4
2. 所有机器执行:内核升级参考:
3. 所有机器执行:安装 docker(注意,Kubernetes 1.16.1 支持的最新版 docker 只能到 18.09,不能安装最新的 docker):
如果已经安装,可以卸载重新安装:
yum -y remove docker-ce yum -y remove docker-ce-cli yum -y remove containerd.io
如果已经安装 etcd 可以卸载并删除 etcd 残余:
yum -y remove etcd
rm -rf /var/lib/etcd
下载 docker 18.09 并安装,下载安装方式和之前一样,注意版本就行:
containerd.io-1.2.6-3.3.el7.x86_64.rpm docker-ce-18.09.9-3.el7.x86_64.rpm docker-ce-cli-18.09.9-3.el7.x86_64.rpm
最终结果如下:
4. 节点 104:安装 harbor:
5. 所有节点:配置 harbor(我这里安装 harbor 的时候指定的域名是这个):
# 每台机器都加入地址解析 echo "192.168.200.104 hub.dylan.com" >> /etc/hosts
给 docker 配置文件添加信任:
echo '{ "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "insecure-registries": ["hub.dylan.com"] }' > /etc/docker/daemon.json
重启 docker:
systemctl daemon-reload
systemctl restart docker
登录 harbor 创建 test 项目测试:
可以进入项目查看推送镜像的方法:
服务器登录 harbor 测试r:
docker login hub.dylan.com
结果如图:
推送测试:
# 重新 tag docker tag nginx:1.17.8 hub.dylan.com/test/nginx:latest # 推送 docker image push hub.dylan.com/test/nginx:latest
查看:
6. 节点 101:准备镜像:
搜索镜像:由于不可描述原因,无法直接从 google 拉取镜像,但是在阿里云镜像仓库中是有人上传了新版镜像的(用户:k8smirrorgooglecontainers):
拉取镜像:可以直接拉取镜像并修改名称即可(注意点击进入查看它提交的版本,有可能更新了和我的不一样):
至于 flannel 镜像则可以查看另外一个用户:dyiwen, 提供了各个版本,我这里都下载以防万一。
docker pull registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/kube-controller-manager:v1.16.1 docker pull registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/kube-apiserver:v1.16.1 docker pull registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/kube-scheduler:v1.16.1 docker pull registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/kube-proxy:v1.16.1 docker pull registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/coredns:1.6.2 docker pull registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/etcd:3.3.15-0 docker pull registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/pause:3.1 # flannel docker pull registry.cn-hangzhou.aliyuncs.com/dyiwen/k8s-flannel:v0.11.0-s390x docker pull registry.cn-hangzhou.aliyuncs.com/dyiwen/k8s-flannel:v0.11.0-ppc64le docker pull registry.cn-hangzhou.aliyuncs.com/dyiwen/k8s-flannel:v0.11.0-arm64 docker pull registry.cn-hangzhou.aliyuncs.com/dyiwen/k8s-flannel:v0.11.0-arm docker pull registry.cn-hangzhou.aliyuncs.com/dyiwen/k8s-flannel:v0.11.0-amd64
重命名镜像:注意,事先创建 kubernetes 项目:
docker image tag registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/kube-controller-manager:v1.16.1 hub.dylan.com/kubernetes/kube-controller-manager:v1.16.1 docker image tag registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/kube-apiserver:v1.16.1 hub.dylan.com/kubernetes/kube-apiserver:v1.16.1 docker image tag registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/kube-scheduler:v1.16.1 hub.dylan.com/kubernetes/kube-scheduler:v1.16.1 docker image tag registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/kube-proxy:v1.16.1 hub.dylan.com/kubernetes/kube-proxy:v1.16.1 docker image tag registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/coredns:1.6.2 hub.dylan.com/kubernetes/coredns:1.6.2 docker image tag registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/etcd:3.3.15-0 hub.dylan.com/kubernetes/etcd:3.3.15-0 docker image tag registry.cn-hangzhou.aliyuncs.com/k8smirrorgooglecontainers/pause:3.1 hub.dylan.com/kubernetes/pause:3.1 # flannel docker image tag registry.cn-hangzhou.aliyuncs.com/dyiwen/k8s-flannel:v0.11.0-s390x hub.dylan.com/kubernetes/flannel:v0.11.0-s390x docker image tag registry.cn-hangzhou.aliyuncs.com/dyiwen/k8s-flannel:v0.11.0-ppc64le hub.dylan.com/kubernetes/flannel:v0.11.0-ppc64le docker image tag registry.cn-hangzhou.aliyuncs.com/dyiwen/k8s-flannel:v0.11.0-arm64 hub.dylan.com/kubernetes/flannel:v0.11.0-arm64 docker image tag registry.cn-hangzhou.aliyuncs.com/dyiwen/k8s-flannel:v0.11.0-arm hub.dylan.com/kubernetes/flannel:v0.11.0-arm docker image tag registry.cn-hangzhou.aliyuncs.com/dyiwen/k8s-flannel:v0.11.0-amd64 hub.dylan.com/kubernetes/flannel:v0.11.0-amd64
推送镜像到私有仓库中:
docker image push hub.dylan.com/kubernetes/etcd:3.3.15-0 docker image push hub.dylan.com/kubernetes/pause:3.1 docker image push hub.dylan.com/kubernetes/kube-scheduler:v1.16.1 docker image push hub.dylan.com/kubernetes/kube-controller-manager:v1.16.1 docker image push hub.dylan.com/kubernetes/kube-apiserver:v1.16.1 docker image push hub.dylan.com/kubernetes/coredns:1.6.2 docker image push hub.dylan.com/kubernetes/kube-proxy:v1.16.1 # flannel docker image push hub.dylan.com/kubernetes/flannel:v0.11.0-s390x docker image push hub.dylan.com/kubernetes/flannel:v0.11.0-ppc64le docker image push hub.dylan.com/kubernetes/flannel:v0.11.0-arm64 docker image push hub.dylan.com/kubernetes/flannel:v0.11.0-arm docker image push hub.dylan.com/kubernetes/flannel:v0.11.0-amd64
删除本地镜像:推送完成后就可以删除本地所有镜像了。
docker image rm -f $(docker image ls -q)
查看结果:此时 harbor 上面的镜像如下:
具体版本:
到此,准备工作完成!
安装 Kubernetes
1. 所有节点:配置安装 kubeadm:
cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=0 repo_gpgcheck=0 gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF
安装:
yum -y install kubeadm-1.16.1 kubectl-1.16.1 kubelet-1.16.1
配置开机自启动但是并不启动它:
systemctl enable kubelet.service
2. 所有节点:拉取并修改镜像,由于步骤较多,可以使用下面脚本,注意修改:
mkdir kubernetes cd kubernetes/ vim Pull-Image.sh
内容如下:
#!/bin/bash ################################################################# # 作用:下载修改 K8S 相关镜像 # 作者:Dy1an <1214966109@qq.com> # 日期:2020-03-09 ################################################################# ################################################################# # 系统相关变量 ################################################################# LINE="----------------------------------------------------------------------------------" HARBOR_REGISTRY=hub.dylan.com/kubernetes K8S_VERSION="v1.16.1" ################################################################# # 拉取镜像 ################################################################# echo ${LINE} echo "开始从 Harbor 镜像仓库(${HARBOR_REGISTRY})拉取 Kubernetes ${K8S_VERSION} 镜像 ......" echo ${LINE} docker image pull ${HARBOR_REGISTRY}/kube-apiserver:${K8S_VERSION} docker image pull ${HARBOR_REGISTRY}/kube-controller-manager:${K8S_VERSION} docker image pull ${HARBOR_REGISTRY}/kube-scheduler:${K8S_VERSION} docker image pull ${HARBOR_REGISTRY}/kube-proxy:${K8S_VERSION} docker image pull ${HARBOR_REGISTRY}/etcd:3.3.15-0 docker image pull ${HARBOR_REGISTRY}/pause:3.1 docker image pull ${HARBOR_REGISTRY}/coredns:1.6.2 # flannel docker image pull ${HARBOR_REGISTRY}/flannel:v0.11.0-s390x docker image pull ${HARBOR_REGISTRY}/flannel:v0.11.0-ppc64le docker image pull ${HARBOR_REGISTRY}/flannel:v0.11.0-arm64 docker image pull ${HARBOR_REGISTRY}/flannel:v0.11.0-arm docker image pull ${HARBOR_REGISTRY}/flannel:v0.11.0-amd64 ################################################################# # 修改 tag ################################################################# echo ${LINE} echo "修改 Kubernetes ${K8S_VERSION} 镜像 tags ......" echo ${LINE} docker image tag ${HARBOR_REGISTRY}/kube-apiserver:${K8S_VERSION} k8s.gcr.io/kube-apiserver:${K8S_VERSION} docker image tag ${HARBOR_REGISTRY}/kube-scheduler:${K8S_VERSION} k8s.gcr.io/kube-scheduler:${K8S_VERSION} docker image tag ${HARBOR_REGISTRY}/kube-controller-manager:${K8S_VERSION} k8s.gcr.io/kube-controller-manager:${K8S_VERSION} docker image tag ${HARBOR_REGISTRY}/kube-proxy:${K8S_VERSION} k8s.gcr.io/kube-proxy:${K8S_VERSION} docker image tag ${HARBOR_REGISTRY}/etcd:3.3.15-0 k8s.gcr.io/etcd:3.3.15-0 docker image tag ${HARBOR_REGISTRY}/pause:3.1 k8s.gcr.io/pause:3.1 docker image tag ${HARBOR_REGISTRY}/coredns:1.6.2 k8s.gcr.io/coredns:1.6.2 # flannel docker image tag ${HARBOR_REGISTRY}/flannel:v0.11.0-s390x quay.io/coreos/flannel:v0.11.0-s390x docker image tag ${HARBOR_REGISTRY}/flannel:v0.11.0-ppc64le quay.io/coreos/flannel:v0.11.0-ppc64le docker image tag ${HARBOR_REGISTRY}/flannel:v0.11.0-arm64 quay.io/coreos/flannel:v0.11.0-arm64 docker image tag ${HARBOR_REGISTRY}/flannel:v0.11.0-arm quay.io/coreos/flannel:v0.11.0-arm docker image tag ${HARBOR_REGISTRY}/flannel:v0.11.0-amd64 quay.io/coreos/flannel:v0.11.0-amd64 ################################################################# # 提示完成 ################################################################# echo ${LINE} echo "拉取 Kubernetes ${K8S_VERSION} 镜像完成,结果如下:" echo ${LINE} docker image ls | grep "k8s.gcr.io"
docker image ls | grep "quay.io"
执行结果如下:
特别说明,在 Kubernetes 中存在三种网络:
1. 节点网络:各台服务器自身的网络,IP 称为 Node IP。
2. Service 网络:各种 Kubernetes 组件的网络,IP 称为 Cluster IP。
3. Pod 网络:运行的 Pod 之间通信的网络,IP 称为 Pod IP。Pod 之间通过 overlay 网络通信,Pod 内部通过 lo 网卡通信。
3. 节点 101:初始化 Master 节点:
# 将配置导出到文件并进行修改 kubeadm config print init-defaults > kubeadm-config.yaml
修改如下:
最后新增的内容如下:
--- apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration featureGates: SupportIPVSProxyMode: true mode: ipvs
执行初始化(将执行结果保留下来,里面有加入集群的重要方法):
kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.log
注意在旧版本中 --upload-certs 参数可能不同。
执行后续操作:
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
查看当前集群节点情况:
kubectl get nodes
结果如图:
可以发现节点属于 NotReady 状态,原因为没安装 flannel,此时安装 flannel:
# 安装配置 wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml # 创建 kubectl create -f kube-flannel.yml
等一段时间后结果如图:
4. 除 Master 101 节点外其它节点:执行 Master 最后输出的命令用于加入集群:
kubeadm join 192.168.200.101:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:2dc5682ed8eb3b681ab74f98e3a90c355ad491904d2562ae74ead54591f2c90a
再度查看:
到此,Kubernetes 集群初始化完成!