学习目标:
- 了解 Kubernetes 的起源和发展
- 掌握如何使用 kubeadm搭建 Kubernetes 集群
- 查看 Kubernetes 集群部署状态
4-1 Kubernetes的起源和发展
Kubernetes 的起源
- Kubernetes最初源于谷歌内部的Borg,Kubernetes 的最初目标是为应用的容器化编排部署提供一个最小化的平台,包含几个基本功能:
- 将应用水平扩容到多个集群
- 为扩容的实例提供负载均衡的策略
- 提供基本的健康检查和自愈能力
- 实现任务的统一调度
Kubernetes 的发展
- 2014年6月 谷歌云计算专家Eric Brewer在旧金山的发布会为这款新的开源工具揭牌。
- 2015年7月22日K8S迭代到 v 1.0并在OSCON大会上正式对外公布。
- 为了建立容器编排领域的标准和规范,Google、RedHat 等开源基础设施领域玩家们,在 2015 年共同牵头发起了名为 CNCF(Cloud Native Computing Foundation)的基金会。Kubernetes 成为 CNCF 最核心的项目。发起成员:AT&T, Box, Cisco, Cloud Foundry Foundation, CoreOS, Cycle Computing, Docker, eBay, Goldman Sachs, Google, Huawei, IBM, Intel, Joyent, Kismatic, Mesosphere, Red Hat, Switch SUPERNAP, Twitter, Univa, VMware and Weaveworks。
- 2018年,超过 1700 开发者成为 Kubernetes 项目社区贡献者,全球有 500 多场沙龙。国内出现大量基于 Kubernetes 的创业公司。
- 2020 年,Kubernetes 项目已经成为贡献者仅次于 Linux 项目的第二大开源项目。成为了业界容器编排的事实标准,各大厂商纷纷宣布支持 Kubernetes 作为容器编排的方案。
4-2 为什么需要 Kubernetes?
传统的容器编排痛点
容器技术虽然解决了应用和基础设施异构的问题,让应用可以做到一次构建,多次部署,但在复杂的微服务场景,单靠 Docker 技术还不够,它仍然有以下问题没有解决:
- 集成和编排微服务模块
- 提供按需自动扩容,缩容能力
- 故障自愈
- 集群内的通信
Kubernetes 能解决的问题
- 按需的垂直扩容,新的服务器(node)能够轻易的增加或删除
- 按需的水平扩容,容器实例能够轻松扩容,缩容
- 副本控制器,你不用担心副本的状态
- 服务发现和路由
- 自动部署和回滚,如果应用状态错误,可以实现自动回滚
什么时候使用 Kubernetes?
- 当你的应用是微服务架构
- 开发者需要快速部署自己的新功能到测试环境进行验证
- 降低硬件资源成本,提高使用率
什么时候不适合使用 Kubernetes
- 应用是轻量级的单体应用,没有高并发的需求
- 团队文化不适应变革
4-3 Kubernetes 的架构和核心概念
主控制节点组件
主控制节点组件对集群做出全局决策(比如调度),以及检测和响应集群事件(例如,当不满足部署的 replicas 字段时,启动新的 pod)。
主控制节点组件可以在集群中的任何节点上运行。 然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有主控制节点组件,并且不会在此计算机上运行用户容器。
- apiserver
主节点上负责提供 Kubernetes API 服务的组件;它是 Kubernetes 控制面的前端组件。 - etcd
etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。 - kube-scheduler
主节点上的组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行。
调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。 - kube-controller-manager
在主节点上运行控制器的组件。
从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。这些控制器包括:- 节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应。
- 副本控制器(Replication Controller): 负责为系统中的每个副本控制器对象维护正确数量的 Pod。
- 终端控制器(Endpoints Controller): 填充终端(Endpoints)对象(即加入 Service 与 Pod)。
- 服务帐户和令牌控制器(Service Account & Token Controllers),为新的命名空间创建默认帐户和 API 访问令牌.
从节点组件
节点组件在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 运行环境。
- kubelet
一个在集群中每个节点上运行的代理。它保证容器都运行在 Pod 中。
kubelet 接收一组通过各类机制提供给它的 PodSpecs,确保这些 PodSpecs 中描述的容器处于运行状态且健康。kubelet 不会管理不是由 Kubernetes 创建的容器。
- kube-proxy
kube-proxy 是集群中每个节点上运行的网络代理,实现 Kubernetes Service 概念的一部分。
kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。 - 容器运行时(Container Runtime)
容器运行环境是负责运行容器的软件。
Kubernetes 支持多个容器运行环境: Docker、 containerd、cri-o、 rktlet 以及任何实现 Kubernetes CRI (容器运行环境接口)。
插件(Addons)
- DNS
尽管其他插件都并非严格意义上的必需组件,但几乎所有 Kubernetes 集群都应该有集群 DNS, 因为很多示例都需要 DNS 服务。 - Web 界面(仪表盘)
Dashboard 是 Kubernetes 集群的通用的、基于 Web 的用户界面。 它使用户可以管理集群中运行的应用程序以及集群本身并进行故障排除。 - 容器资源监控
容器资源监控 将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中,并提供用于浏览这些数据的界面。 - 集群层面日志
集群层面日志 机制负责将容器的日志数据 保存到一个集中的日志存储中,该存储能够提供搜索和浏览接口。
4-4 Kubernetes 的部署方案介绍
部署目标
- 在所有节点上安装Docker和kubeadm
- 部署Kubernetes Master
- 部署容器网络插件
部署架构
| ip | 域名 | 备注 | 安装软件 |
|---|---|---|---|
| 192.168.99.101 | master | 主节点 | Docker Kubeadm kubelet kubectl flannel |
| 192.168.99.102 | node1 | 从节点 1 | Docker Kubeadm kubelet kubectl |
| 192.168.99.103 | node2 | 从节点 2 | Docker Kubeadm kubelet kubectl |
环境准备
- 3台虚拟机CentOS7.x-86_x64
- 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多
- 集群中所有机器之间网络互通
- 可以访问外网,需要拉取镜像
- 禁止swap分区
4-5 Virtualbox 虚拟机配置双网卡实现固定IP
- Virtualbox安装 CentOS
- 配置虚机双网卡,实现固定 IP,且能访问外网
网卡 1: 仅主机host-only
网卡 2: 网络转换地址NAT
查看虚拟机网络,点击管理—>主机网络管理器,记住ip地址(192.168.99.1),并选择“手动配置网卡”。 - 重启虚拟机,此时在虚拟机 ping www.baidu.com 是返回成功的。
- 设置外部网络访问虚拟机
设置静态ip地址,编辑网络配置文件,编辑网络设置文件
vi /etc/sysconfig/network-scripts/ifcfg-enp0s3TYPE=EthernetPROXY_METHOD=noneBROWSER_ONLY=no#BOOTPROTO=dhcpDEFROUTE=yesIPV4_FAILURE_FATAL=noIPV6INIT=yesIPV6_AUTOCONF=yesIPV6_DEFROUTE=yesIPV6_FAILURE_FATAL=noIPV6_ADDR_GEN_MODE=stable-privacyNAME=enp0s3UUID=08012b4a-d6b1-41d9-a34d-e0f52a123e7aDEVICE=enp0s3ONBOOT=yesBOOTPROTO=staticIPADDR=192.168.99.101
- 重启网络
systemctl restart network
- 查看 enp0s3 网卡的 ip
[root@localhost Final]#ip addr |grep 192inet 192.168.99.101/24 brd 192.168.99.255 scope global noprefixroute enp0s3
- 此时虚拟机既可以访问外网,也能够和宿主机( 192.168.31.178)进行通信
ping 192.168.31.178PING 192.168.31.178 (192.168.31.178): 56 data bytes64 bytes from 192.168.31.178: icmp_seq=0 ttl=64 time=0.060 ms
- 使用iTerm2 连接虚拟机
4-6 Master节点安装 kubeadm, kubelet and kubectl
- 配置 Master 和 work 节点的域名
vim /etc/hosts192.168.56.101 master192.168.56.102 node1192.168.56.103 node2
- 设置域名解析服务器
vi /etc/resolv.conf# Generated by NetworkManagersearch lannameserver 114.114.114.114

剩余步骤可通过这个脚本执行: base_install.sh
- 下载阿里云的yum源:
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
- 安装基本软件包
[root@localhost ~]# yum install wget net‐tools ntp vim bash‐comp* ‐y
同步系统时间
yum install -y ntpdatentpdate ntp3.aliyun.com
将桥接的IPv4流量传递至iptables的链
[root@master ~]# modprobe br_netfilter[root@master ~]# echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptables[root@master ~]# vi /etc/sysctl.d/k8s.confnet.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1

关闭 防火墙
systemctl stop firewalldsystemctl disable firewalld
- 关闭 SeLinux
setenforce 0sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
也可以修改 /etc/selinux/config 文件,如图片中所示
- 关闭 swap
swapoff -ayes | cp /etc/fstab /etc/fstab_bakcat /etc/fstab_bak |grep -v swap > /etc/fstab
也可以直接编辑 /etc/fstab 文件注释掉图片的内容
- free -m 发现swap全为0表示设置成功

- 设置主机名,管理节点设置主机名为master
[root@master ~]# hostnamectl set-hostname master[root@master ~]# su ‐
- 配置Docker, K8S的阿里云yum源
[root@master ~]# cat >>/etc/yum.repos.d/kubernetes.repo <<EOF[kubernetes]name=Kubernetesbaseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/enabled=1gpgcheck=1repo_gpgcheck=1gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpgEOF[root@master ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo[root@master ~]# yum repolist
- 安装并启动 docker
yum install -y yum-utils device-mapper-persistent-data lvm2yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repoyum -y install docker-cemkdir /etc/dockercat > /etc/docker/daemon.json <<EOF{"registry-mirrors": ["https://6yus5ux3.mirror.aliyuncs.com"],"exec-opts": ["native.cgroupdriver=systemd"]}EOF
如果报错如下,则重新下载 wget -O /etc/yum.repos.d/CentOS-Base.repo [http://mirrors.aliyun.com/repo/Centos-7.repo](http://mirrors.aliyun.com/repo/Centos-7.repo)
如果还不行就使用以下脚本:
curl -fsSL get.docker.com -o get-docker.shbash get-docker.sh
- 编辑/usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd
# Restart Dockersystemctl daemon-reloadsystemctl enable dockersystemctl restart docker
此时查看 docker info,可以看到默认 Cgroup Driver为 systemd
- 卸载旧版本
yum remove -y kubelet kubeadm kubectl
- 安装kubelet、kubeadm、kubectl
yum install -y kubelet kubeadm kubectl
- 重启 docker,并启动 kubelet
systemctl enable kubelet && systemctl start kubelet
之后便可给Master节点打上快照,然后worker节点便可用这个快照进行构建。
4-8 初始化Master 节点
- 设置主机名,管理节点设置主机名为master
[root@master ~]# hostnamectl set-hostname master[root@master ~]# su ‐
- 将桥接的IPv4流量传递到iptables的链
echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptablesvi /etc/sysctl.d/k8s.confnet.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1
剩余操作可通过以下脚本执行:注意修改版本和节点地址 init_master.sh

- 初始化主节点
kubeadm init --kubernetes-version=1.23.1 \--apiserver-advertise-address=192.168.56.101 \--image-repository registry.aliyuncs.com/google_containers \--service-cidr=10.1.0.0/16 \--pod-network-cidr=10.244.0.0/16
mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configecho "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
- 初始化完成后记住图片中的内容(token),用于node节点的搭建
```bash
kubeadm join 192.168.56.101:6443 —token j0tuuf.p635m3gjlcn3d2w7 \
--discovery-token-ca-cert-hash sha256:b072d61cbfe86def68800a610e2f9eac45c34e83a55c6dab14691bf8a64cd4c1
- 检查节点信息```bash[root@master ~]# kubectl get nodeNAME STATUS ROLES AGE VERSIONmaster NotReady control-plane,master 6m26s v1.23.1
- 安装网络插件 Flannel
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
- 如果下载文件失败,或者无法从 quay.io/coreos 下载镜像,则可以使用代码库:
或者这个链接:flannel.yml
kubectl apply -f kubeblog/docs/Chapter4/flannel.yaml

> 这个文件将flannel镜像上传到了dockerhub https://hub.docker.com/repository/docker/wangqingjiewa/flannel查看kube-system状态 ```bash [root@master ~]# kubectl get po -n kube-system NAME READY STATUS RESTARTS AGE coredns-6d8c4cb4d-r7q7n 1/1 Running 0 17m coredns-6d8c4cb4d-sfqlb 1/1 Running 0 17m etcd-master 1/1 Running 0 18m kube-apiserver-master 1/1 Running 0 18m kube-controller-manager-master 1/1 Running 0 18m kube-flannel-ds-chd2n 1/1 Running 0 101s kube-proxy-p42n2 1/1 Running 0 17m kube-scheduler-master 1/1 Running 0 18m
- 查看master节点状态已经是ready```bash[root@master ~]# kubectl get nodeNAME STATUS ROLES AGE VERSIONmaster Ready control-plane,master 21m v1.23.1
- 查看是否成功创建flannel网络
ifconfig |grep flannel
报错处理
如果出现“node ‘master’ not found”错误
# 检查权限chmod 777 /run/flannel/subnet.env
如果flannel pod启动失败,执行以下命令查看报错信息
kubectl describe pod kube-flannel-ds-xxx -n kube-system
如果是镜像拉取失败,可尝试修改 quay.io 的镜像路径。可以执行以下命令,并将结果保存至flannel.yml,修改 quay.io 的镜像路径,再执行delete和create操作
kubectl get pod kube-flannel-ds-xx -n kube-system -o yamlkubectl delete -f flannel.yamlkubectl create -f flannel.yaml
查看运行的Kubernetes组件
docker ps
如果出现“The connection to the server 192.168.56.101:6443 was refused - did you specify the right host or port?”错误
先执行:kubectl get po -n kube-system,查看所有服务是否正常启动,如果某个服务启动失败,则执行kubectl describe pod <pod name> -n kube-system
查看错误原因。重置 kubeadm
kubeadm reset
4-9 安装配置 worker Node节点
- 初始虚拟机,Centos,配置双网卡


注意 clone snapshot 虚拟机时,选择’Generate new MAC address’。 - ssh 免密登录
- 设置 ip 地址为 192.168.99.102
- 配置域名
hostnamectl set-hostname node1vi /etc/hosts192.168.99.101 master192.168.99.102 node1192.168.99.103 node2
机器间互相免密,配置完成后需要重启机器
yum install openssh-serverssh-keygen -t rsassh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.56.101reboot -f
如果安装有报错:没有安装deltarpm就执行以下命令 yum provides ‘*/applydeltarpm’ yum -y install deltarpm
将 master 节点的 admin.conf 拷贝到 node1
scp /etc/kubernetes/admin.conf root@node1ip:/etc/kubernetes/
配置端口转发
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptablesecho 1 > /proc/sys/net/ipv4/ip_forward
配置 Kubeconfig 环境变量
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profilesource ~/.bash_profile
安装网络相关的工具
yum install net-tools
加入集群之前先清理拷贝过来的Master环境的网络
kubeadm resetsystemctl stop kubeletsystemctl stop dockerrm -rf /var/lib/cni/rm -rf /var/lib/kubelet/*rm -rf /etc/chi/ifconfig cni0 downifconfig flannel.1 downifconfig docker0 downip link delete cni0ip link delete flannel.1systemctl start dockersystemctl start kubelet
cni是指container network interface。
kubadm join 加入集群
systemctl enable kubelet.servicekubeadm join 192.168.99.101:6443 --token vrqf1w.dyg1wru7nz0ut9jz --discovery-token-ca-cert-hash sha256:1832d6d6c8386de5ecb1a7f512cfdef27a6d14ef901ffbe7d3c01d999d794f90
默认token的有效期为24小时,当过期之后,该token就不可用了。解决方法如下:
重新生成新的token,在master端执行
kubeadm token create --print-join-command
- 安装 flannel 网络插件
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
- 将master节点下面 /etc/cni/net.d/下面的所有文件拷贝到node节点上
在node1节点上面创建目录:mkdir -p /etc/cni/net.d/
在master:scp /etc/cni/net.d/* root@nodeip:/etc/cni/net.d/
执行命令:kubectl get nodes 查看 node 节点处于ready状态
- 检查集群状态
稍等几分钟,在master节点输入命令检查集群状态.
kubectl get nodes

4-10 剖析kubeadm安装原理
Init 命令的工作流程
kubeadm init命令通过执行下列步骤来启动一个 Kubernetes Control Plane节点。
运行一系列的预检项来验证系统状态。一些检查项目仅仅触发警告, 其它的则会被视为错误并且退出
kubeadm,除非问题得到解决或者用户指定了--ignore-preflight-errors=参数。生成一个自签名的CA证书(或者使用现有的证书,如果提供的话)来为集群中的每一个组件建立身份标识。如果用户已经通过
--cert-dir配置的证书目录(默认为/etc/kubernetes/pki)提供了他们自己的 CA 证书以及/或者密钥,那么将会跳过这个步骤,正如文档使用自定义证书所述。将
kubeconfig文件写入/etc/kubernetes/目录,以便kubelet、控制器管理器和调度器用来连接到API 服务器,它们每一个都有自己的身份标识,同时生成一个名为admin.conf的独立的kubeconfig文件,用于管理操作。为 API服务器、控制器管理器和调度器生成静态Pod的清单文件。静态Pod的清单文件被写入到
/etc/kubernetes/manifests目录;kubelet 会监视这个目录以便在系统启动的时候创建 Pod。一旦Control Plane的 Pod 都运行起来,kubeadm init的工作流程就继续往下执行。对
Control Plane节点应用 labels 和 taints 标记以便不会在它上面运行其它的工作负载。生成令牌以便其它节点以后可以使用这个令牌向
Control Plane节点注册自己。Kubeadm会创建configmap,提供添加节点所需要的信息。
查看创建的configmap


安装问题
- 用
docker ps -a查看Kubernetes系统服务的状态 Kubernetes集群启动问题,用journalctl查看日志
systemctl status kubeletjournalctl -xefu kubeletjournalctl -u kube-apiserver
用kubectl查看日志
注意:使用Kubelet describe 查看日志,一定要注意是否应包含命名空间
kubectl describe pod kubernetes-dashboard-xxx --namespacekubectl logs -f pods/monitoring-influxdb-xxx -n kube-systemkubectl logs --tail 200 -f podname -n jenkins
- 执行
kubeadm join异常问题
执行 kubeadm reset,并且将 cni0,flannel1.1,docker0等网络规则删除,参考 Worker node 安装的章节。
- 镜像拉取不下来
修改 yaml 文件中的 image路径
4-11 安装Dashboard
- 下载Kubernetes Dashboard yaml 文件
https://www.yuque.com/insaneloafer/eqq96o/kssab0?inner=ltYwM
- 修改Service类型为NodePort

spec:type: NodePortports:- port: 443targetPort: 8443nodePort: 31111selector:k8s-app: kubernetes-dashboard
部署dashboard
kubectl create -f kubernetes-dashboard.yamlkubectl apply -f kubernetes-dashboard.yaml

查看pod、svc状态
kubectl get pod,svc -n kubernetes-dashboard

非安全的浏览器访问
通过chrome浏览器访问https://192.168.99.102:31111,此时会返回“Your connection is not private”,无法跳转页面到Dashboard,这是由于 chrome 的安全设置,解决办法:鼠标点击当前页面,直接键盘输入’thisisunsafe’,然后回车,即可进行页面跳转至 Dashboard登录页
获取登录 token
kubectl -n kube-system describe $(kubectl -n kube-system get secret -n kube-system -o name | grep namespace) | grep token

登录 Dashboard
在登录页面输入之前生成的 token,即可完成登录。

