使用 Kubeadm 部署 Kubernetes 集群
前言
Kubernetes 相关简介
首先,它是一个全新的基于容器技术的分布式架构领先方案。这个方案虽然还很新,但它是谷歌十几年以来大规模应用容器技术的经验积累和升华的一个重要成果。确切地说,Kubernetes 是谷歌严格保密十几年的秘密武器----Borg 的一个开源版本。Borg 是谷歌的一个久负盛名的内部使用的大规模集群管理系统,它基于容器技术,目的是实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。
在 Kubernetes 中,Service(服务)是分布式集群架构的核心,一个 Service 对象拥有如下关键特征:
- 拥有一个唯一指定的名字(比如 mysql-server)
- 拥有一个虚拟 IP(Cluster IP、Service IP 或 VIP)和端口号
- 能够提供某种远程服务能力
- 被映射到了提供这种服务能力的一组容器应用上
Service 的服务进程目前都基于 Socket 通信方式对外提供服务,比如 Redis、Memcache、MySQL、Web Service,或者是实现某个具体业务的一个特定的 TCP Server 进程。容器提供了强大的隔离功能,所以有必要把为 Service 提供服务的这组进程放入容器中进行隔离。为此,Kubernetes 设计了 Pod 对象,将每个服务进程封装到相应的 Pod 中,使其成为 Pod 中运行的一个容器(Container)。为了建立 Service 和 Pod 间的关联关系,Kubernetes 首先给每个 Pod 贴上一个标签(Label),如给运行 MySQL 的 Pod 贴上 name=mysql 标签,给运行 PHP 的 Pod 贴上 name=php 标签,然后给相应的 Service 定义标签选择器(Label Selector),比如 MySQL Service 的标签选择器的选择条件为 name=mysql,意为该 Service 要作用于所有包含 name=mysql Label 的 Pod 上。
Kubernetes 优点
- 自动装箱、自我修复、水平扩展、服务发现和负载均衡、自动发布和回滚
- 密钥和配置管理、存储编排、批量处理执行
Kubernetes 介绍
在集群管理方面,Kubernetes 将集群中的机器划分为一个 Master 节点和一群工作节点(Node)。
Master 节点上运行着集群管理相关的一组进程 kube-apiserver、kube-controller-manager 和 kube-scheduler,这些进程实现了整个集群的资源管理、Pod 调度、弹性伸缩、安全控制、系统监控和纠错等管理功能,并且都是全自动完成的。
Node 作为集群中的工作节点,运行着真正的应用程序,在 Node 上 Kubernetes 管理的最小运行单元是 Pod。Node 上运行着 Kubernetes 的 kubelet、kube-proxy 服务进程,这些服务进程负责 Pod 的创建、启动、监控、重启、销毁,以及实现软件模式的负载均衡器。
master 节点
Master 节点上运行着以下一组关键进程
- Kubernetes API Server(kube-apiserver),提供了 HTTP Rest 接口的关键服务进程,是 Kubernetes 里所有资源的增、删、改、查等操作的唯一入口,也是集群控制的入口进程。
- Kubernetes Controller Manager(kube-controller-manager),Kubernetes 里所有资源对象的自动化控制中心,可以理解为资源对象的“大总管”。
- Kubernetes Scheduler(kube-scheduler),负责资源调度(Pod 调度)的进程,相当于公交公司的“调度室”。
其实 Master 节点上往往还启动了一个 etcd Server 进程,因为 Kubernetes 里的所有资源对象的数据全部是保存在 etcd 中的。
node 节点
除了 Master,Kubernetes 集群中的其他机器被称为 Node 节点,在较早的版本中也被称为 Minion。与 Master 一样,Node 节点也可以是一台物理主机,也可以是一台虚拟机。Node 节点才是 Kubernetes 集群中的工作负载节点,每个 Node 都会被 Master 分配一些工作负载(Docker 容器),当某个 Node 宕机时,其上的工作负载会被 Master 自动转移到其他节点上去。每个 Node 节点上都运行着以下一组关键进程。
- kubelet:负责 Pod 对应的容器的创建、启停等任务,同时与 Master 节点密切协作,实现集群管理的基本功能。
- kube-proxy:实现 Kubernetes Service 的通信与负载均衡机制的重要组件。
- Docker Engine(docker):Docker 引擎,负责本机的容器创建和管理工作。
Pod
Pod 是 Kubernetes 的最重要也最基本的概念,每个 Pod 都有一个特殊的被称为“根容器”的 Pause 容器。Pause 容器对应的景象属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 还包含一个活多个紧密相关的用户业务容器。假如 pod 里面有 php-fpm 和 nginx 两个容器,他们首先不能端口冲突,其次,##他们都是共享 pause 容器的。
Pod 其实有两种类型:普通的 Pod 及静态 Pod(static Pod),后者比较特殊,它并不存放在 Kubernetes 的 etcd 存储里,而是存放在某个具体的 Node 上的一个具体文件中,并且只在此 Node 上启动运行。而普通的 Pod 一旦被创建,就会被放入到 etcd 中存储,随后会被 Kubernetes Master 调度到某个具体的 Node 上并进行绑定(Binding),随后该 Pod 被对应的 Node 上的 kubelet 进程实例化成一组相关的 Docker 容器并启动起来。在默认情况下,当 Pod 里的某个容器停止时,Kubernetes 会自动检测到这个问题并且重新启动这个 Pod(重启 Pod 里的所有容器),如果 Pod 所在的 Node 宕机,则会将这个 Node 上的所有 Pod 重新调度到其它节点上。Pod、容器与 Node 的关系图如下:
K8S 结构图
etcd 内部架构图
各组件的作用
master 节点组件作用:
- CrontrollerManager:维护副本期望数目的作用。
- scheduler:资源调度器,选择合适的节点把任务交给 api server 分配任务。
- api server:一切服务访问的统一入口,任何东西都要跟它进行交互。把接收到的各类信息,写入到 etcd 中进行存储。
- etcd:是 go 语言编写的键值对的分布式的存储数据库。存储 k8s 的关键数据,协助集群正常运转。
node 节点组件作用:
- kubelet:C(容器) R(运行环境) I(接口) 直接跟容器引擎进行交互实现维护 pod 的生命周期。
- kube-proxy:负责规则写入 iptables、ipvs,实现访问、负载均衡等作用
其他组件:
- CoreDNS:可以为集群中的 svc 创建一个域名 ip 的对应关系解析
- Dashboard:给 k8s 集群提供一个 B/S 结构访问体系
- INGRESS controller:官方只能实现 4 层代理,Ingress 可以实现 7 层代理
- Federation:提供一个可以跨集群中心多 K8S 统一管理功能
- prometheus:提供一个 k8s 的集群的监控能力
- ELK:提供 K8S 集群日志统一分析接入平台。
安装环境
组件明细
部署节点说明
部署过程
系统初始化环境准备
1、分别设置每台服务器的主机名和本地 hosts
- 设置主机名
hostnamectl set-hostname k8s-masterhostnamectl set-hostname k8s-node01hostnamectl set-hostname k8s-node02
- 写本地 hosts
cat <<EOF >>/etc/hosts 192.168.100.101 k8s-master192.168.100.102 k8s-node01192.168.100.103 k8s-node02 EOF
2、禁用防火墙、selinux 和 swap
systemctl stop firewalldsystemctl disable firewalldsetenforce 0sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/configswapoff -ased -i 's/.*swap.*/#&/' /etc/fstab
3、配置相关内核参数
cat > /etc/sysctl.d/k8s.conf <<EOF net.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1net.ipv4.ip_forward = 1EOF modprobe br_netfiltersysctl -p /etc/sysctl.d/k8s.conf
4、配置 ipvs 相关模块
yum install ipset ipvsadm -y cat > /etc/sysconfig/modules/ipvs.modules <<EOF#!/bin/bashmodprobe -- ip_vsmodprobe -- ip_vs_rrmodprobe -- ip_vs_wrrmodprobe -- ip_vs_shmodprobe -- nf_conntrack_ipv4EOFchmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
5、同步时间
# 安装 ntpdateyum install ntpdate -y # 同步本地时间ntpdate time.windows.com # 跟网络源做同步ntpdate cn.pool.ntp.org # 时间同步定时任务crontab -e* */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org # 重启 crond 服务service crond restart
集群组件安装
1、安装 docker 环境
- 配置国内 yum 源
yum install -y yum-utils device-mapper-persistent-data lvm2yum-config-manager \ --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 查看当前 docker 版本列表
yum list docker-ce.x86_64 --showduplicates |sort -rdocker-ce.x86_64 3:20.10.0-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.9-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.8-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.7-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.6-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.5-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.4-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.3-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.2-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.14-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.1-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.13-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.13-3.el7 @docker-ce-stabledocker-ce.x86_64 3:19.03.12-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.11-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.10-3.el7 docker-ce-stable docker-ce.x86_64 3:19.03.0-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.9-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.8-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.7-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.6-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.5-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.4-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.3-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.2-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.1-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
- 安装指定版本(需在 kubeadm 当前支持的版本列表内)
yum install -y --setopt=obsoletes=0 docker-ce-19.03.9-3.el7
- 设置普通用户免 sudo 运行,启动服务
sudo groupadd dockersudo gpasswd -a ${USER} dockernewgrp docker systemctl start dockersystemctl enable docker
- 修改 docker 默认的 cgroup driver 为 systemd
- 查看最大的磁盘路径,修改 data-root 的路径,/var/lib/docker 为默认路径,如果需要独立数据盘,请重新格式化数据盘并修改 data-root 路径。
$ cat>/etc/docker/daemon.json<<'EOF'{ "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "data-root": "/var/lib/docker", "log-opts": { "max-size": "100m", "max-file": "10" }, "oom-score-adjust": -1000, "registry-mirrors": ["https://registry.docker-cn.com"], "storage-driver": "overlay2", "storage-opts":["overlay2.override_kernel_check=true"], "live-restore": true}EOF $ systemctl restart docker $ docker info | grep CgroupCgroup Driver: systemd
2、安装 Kubeadm 相关组件
- 配置国内 kubernetes 源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/enabled=1gpgcheck=0repo_gpgcheck=0gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF
- 安装指定版本的组件(需要跟目标集群版本一致,此处为 1.19.4)
yum install -y kubelet-1.19.4 kubeadm-1.19.4 kubectl-1.19.4systemctl enable kubelet
Master 节点部署
1、使用 kubeadm 初始化集群
kubeadm init --kubernetes-version=1.19.4 \ --apiserver-advertise-address=10.200.14.112 \ --image-repository=registry.aliyuncs.com/google_containers \ --service-cidr=10.10.0.0/16 \ --pod-network-cidr=10.1.0.0/16
此处定义 api-server 地址为 master 内网网卡 IP 地址,POD 网段为 10.1.0.0/16
2、集群初始化成功后会返回如下信息,此命令需要后续阶段在其他 node 节点执行
kubeadm join 10.200.14.112:6443 --token fm08rl.5xpr14nhs83p729w \ --discovery-token-ca-cert-hash sha256:44850f41f4567417491f4ef5591f189765b279f5bc2d876fc5e8ce3edc0c87e5
3、配置 kubectl 工具
mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config #自动补全yum install -y bash-completionecho "source /usr/share/bash-completion/bash_completion" >> ~/.bashrcecho "source <(kubectl completion bash)" >> ~/.bashrc
4、检查集群健康状态
$ kubectl get csNAME STATUS MESSAGE ERRORcontroller-manager Healthy ok scheduler Healthy ok etcd-0 Healthy {"health":"true"}etcd-1 Healthy {"health":"true"}etcd-2 Healthy {"health":"true"}
- 如果 controller-manager 和 scheduler 状态为 Unhealthy
# sed -i '/--port\=0/ s/^\(.*\)$/#\1/g' /etc/kubernetes/manifests/kube-controller-manager.yaml# sed -i '/--port\=0/ s/^\(.*\)$/#\1/g' /etc/kubernetes/manifests/kube-scheduler.yaml# systemctl restart kubelet
5、如果在集群初始化过程中遇到问题,需要执行以下命令清理环境
kubeadm resetifconfig cni0 downip link delete cni0ifconfig flannel.1 downip link delete flannel.1rm -rf /var/lib/cni/rm -rf /var/lib/etcd/*
复制代码
Flannel 网络组件部署
1、部署 Flannel 网络组件
这里注意需要修改文件配置里 pod 网段,与初始化时--pod-network-cidr
时指定的网段一致。如果报错直接去浏览器复制粘贴。
#wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml #sed -i 's/10.244.0.0\/16/10.1.0.0\/16/g' kube-flannel.yml #kubectl apply -f kube-flannel.yml
flannel 默认会选择服务器的 eth0 网卡,如果服务器存在多网卡,则需手动指定内网网卡名称。
......containers: - name: kube-flannel image: quay.io/coreos/flannel:v0.11.0-amd64 command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr - --iface=eth1......
2、检查集群系统相关组件状态是否正常
$ kubectl get pod -n kube-systemNAME READY STATUS RESTARTS AGEcoredns-7b7df549dd-m2jtg 1/1 Running 0 13hcoredns-7b7df549dd-p7hwl 1/1 Running 0 13hetcd-kmaster 1/1 Running 0 13hkube-apiserver-kmaster 1/1 Running 0 13hkube-controller-manager-kmaster 1/1 Running 0 13hkube-flannel-ds-amd64-5vtp6 1/1 Running 0 13hkube-flannel-ds-amd64-hsdh7 1/1 Running 0 13hkube-proxy-7tn8w 1/1 Running 0 13hkube-proxy-nl8bd 1/1 Running 0 13hkube-scheduler-kmaster 1/1 Running 0 13h
3、测试集群 DNS 是否正常工作
- 运行 curl 工具容器测试解析
$ kubectl run curl --image=radial/busyboxplus:curl -it[ root@curl-65f88748fd-5p4cm:/ ]$ nslookup kubernetes.default Server: 10.1.0.10Address 1: 10.1.0.10 kube-dns.kube-system.svc.cluster.local Name: kubernetes.defaultAddress 1: 10.1.0.1 kubernetes.default.svc.cluster.loca
Node 节点部署
1、在其余两台 node 节点上执行 Master 初始化完成显示的命令:
kubeadm join 192.168.100.101:6443 --token osru8w.rd9l1jz4iipyxq3t \ --discovery-token-ca-cert-hash sha256:16fbd998a83d22b65089a0c519ec819a5f8ecebe918b551e52fe6b1717ec10c0
2、在 master 上执行集群状态检测
$ kubectl get nodesNAME STATUS ROLES AGE VERSIONk8s-master Ready master 13h v1.19.4k8s-node01 Ready <none> 13h v1.19.4k8s-node02 Ready <none> 13h v1.19.4
STATUS 均为 Ready,说明集群状态正常。
3、部署完成后,master 节点上默认存在不接受普通 Pod 调度的 taints,可以执行以下命令取消:
kubectl taint nodes k8s-master node-role.kubernetes.io/master:NoSchedule-
这样,普通的 Pod 也可以调度到 master 节点上了。
部署应用测试
1、创建 Nginx 容器
$ kubectl create deployment nginx --image=nginx$ kubectl expose deployment nginx --port=80 --type=NodePort$ kubectl get pod,svcNAME READY STATUS RESTARTS AGEpod/nginx-6799fc88d8-ghcpv 1/1 Running 0 3m1spod/nginx-6799fc88d8-njj6p 1/1 Running 0 3mpod/nginx-6799fc88d8-zvztr 1/1 Running 0 3m24s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/kubernetes ClusterIP 10.10.0.1 <none> 443/TCP 9m6sservice/nginx NodePort 10.10.194.166 <none> 80:31293/TCP 3m19s
2、本机访问 nginx 的 svc,返回如下结果则正常
$ curl 10.10.194.166 -IHTTP/1.1 200 OKServer: nginx/1.19.4Date: Fri, 13 Nov 2020 05:51:06 GMTContent-Type: text/htmlContent-Length: 612Last-Modified: Tue, 27 Oct 2020 15:09:20 GMTConnection: keep-aliveETag: "5f983820-264"Accept-Ranges: bytes
集群中加入 master 节点
1、得到加入集群的 KEY
kubeadm init phase upload-certs --experimental-upload-certs
执行结果如下:
[root@k8s-master ~]# kubeadm init phase upload-certs --upload-certsI0122 08:01:15.517893 60086 version.go:252] remote version is much newer: v1.23.2; falling back to: stable-1.18W0122 08:01:17.049273 60086 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io][upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace[upload-certs] Using certificate key:5d817a5480c54bb079eab4f7b75b4dfe21bd36e059dfb46bf39f724adb3349aa
2、得到加入集群的 token
kubeadm token create --print-join-command
执行结果如下:
[root@k8s-master ~]# kubeadm token create --print-join-commandW0122 08:01:19.445355 60121 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]kubeadm join 172.16.64.2:6443 --token xhsmiv.ggj00ojs6dvv8b23 --discovery-token-ca-cert-hash sha256:5211bd42a2e81b933b52ec83686f93ae6212542d22d00c621fad20f0dc9592b4
3、将得到的 token 和 key 进行拼接,得到如下命令:
kubeadm join 192.168.92.129:6443 --token xhsmiv.ggj00ojs6dvv8b23 --discovery-token-ca-cert-hash sha256:5211bd42a2e81b933b52ec83686f93ae6212542d22d00c621fad20f0dc9592b4 --control-plane --certificate-key 5d817a5480c54bb079eab4f7b75b4dfe21bd36e059dfb46bf39f724adb3349aa
注意事项:
1、不要使用 --experimental-control-plane,会报错 2、要加上--control-plane --certificate-key,不然就会添加为node节点而不是master 3、join的时候节点上不要部署,如果部署了kubeadm reset后再join
4、 第一次加入集群的时候会有以下报错:
[preflight] Running pre-flight checks[preflight] Reading configuration from the cluster...[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'error execution phase preflight:One or more conditions for hosting a new control plane instance is not satisfied. unable to add a new control plane instance a cluster that doesn't have a stable controlPlaneEndpoint address Please ensure that:* The cluster has a stable controlPlaneEndpoint address.* The certificates that must be shared among control plane instances are provided. To see the stack trace of this error execute with --v=5 or higher
5、主节点上在 kubeadm-config 中添加 controlPlaneEndpoint 大概在这么个位置:
kind: ClusterConfigurationkubernetesVersion: v1.18.0controlPlaneEndpoint: 172.16.64.2:6443
然后再在准备添加为 master 的节点上执行 kubeadm join(第三步)的命令
6、成功
This node has joined the cluster and a new control plane instance was created: * Certificate signing request was sent to apiserver and approval was received.* The Kubelet was informed of the new secure connection details.* Control plane (master) label and taint were applied to the new node.* The Kubernetes control plane instances scaled up.* A new etcd member was added to the local/stacked etcd cluster. To start administering your cluster from this node, 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 Run 'kubectl get nodes' to see this node join the cluster.