k8s集群安装教程

安装方式介绍

kubernetes官网地址:国外网站,访问速度较慢。 https://kubernetes.io/

kubernets中文社区地址: https://www.kubernetes.org.cn/

k8s集群部署方式:

    1. 使用minikube安装单节点集群,用于测试
    2. 采用工具kubeadm
    3. 使用kubespray,google官方提供的工具。
    4. 全手动:二进制方式安装
    5. 全自动安装:rancher 、kubesphere

本篇主要介绍使用第二种方案,使用kubeadm 安装方式k8s集群

环境准备

虚拟机安装及配置,以及docker安装、镜像加速等配置本文略过,自行准备好基础环境。感兴趣的可以参考这篇博客:CentOS7虚拟机配置及Docker环境安装。我这边使用3台虚拟机安装k8s,配置如下。

主机名 主机IP 配置
k8s-master01 192.168.1.201 2c4g
k8s-node01 192.168.1.202 2c4g
k8s-node02 192.168.1.203 2c4g

本地CentOS版本和Docker版本如下:

1
2
3
4
5
[root@k8s-master01 ~]# cat /etc/centos-release
CentOS Linux release 7.9.2009 (Core)
[root@k8s-master01 ~]# docker -v
Docker version 20.10.1, build 831ebea
[root@k8s-master01 ~]#

四台服务器执行如下脚本,追加host配置

1
2
3
4
5
cat >>/etc/hosts<<EOF
192.168.1.201 k8s-master
192.168.1.202 k8s-slave1
192.168.1.203 k8s-slave2
EOF

小技巧提示:因为后续安装可能比较容易出错,要删除重新安装会比较麻烦,我们这里基础环境准备好之后可以使用虚拟机工具存储当前快照,如果安装有问题,可以快速复制一个新的虚拟机来进行安装

使用kubeadm快速安装

软件 说明 版本
kubeadm 初始化集群管理 集群 版本 1.17.5
kubelet 用于接收api-server指令,对 pod生命周期进行管理 1.17.5
kubectl 集群命令行管理 工具 1.17.5

安装yum源

新建repo文件

1
vim /etc/yum.repos.d/kubernates.repo

添加内容

1
2
3
4
5
6
7
8
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

保存之后更新缓存

1
2
yum clean all
yum -y makecache

验证源是否可用

1
2
3
yum list | grep kubeadm
如果提示要验证yum-key.gpg是否可用,输入y。
查找到kubeadm。显示版本

查看k8s版本,最新的已经更新到1.18

1
yum list kubelet --showduplicates | sort -r

这里安装最好不使用最新的,选择一个比较稳定的版本(本文使用1.17.5)

设置kubelet

增加配置信息,这一步是为了实现docker使用的cgroupdriver与kubelet使用的cgroup的一致性。如果不配置kubelet,可能会导致K8S集群无法启动。

1
vi /etc/sysconfig/kubelet

增加如下内容

1
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"

设置开机启动

1
systemctl enable kubelet

初始化镜像

如果是第一次安装k8s,手里没有备份好的镜像,可以在master节点执行如下操作下载

查看安装集群需要的镜像

1
2
3
4
5
6
7
8
9
10
11
12
[root@k8s-master01 ~]# kubeadm config images list
I0301 16:53:34.060015 40408 version.go:251] remote version is much newer: v1.26.2; falling back to: stable-1.17
W0301 16:53:35.101892 40408 validation.go:28] Cannot validate kube-proxy config - no validator is available
W0301 16:53:35.101958 40408 validation.go:28] Cannot validate kubelet config - no validator is available
k8s.gcr.io/kube-apiserver:v1.17.17
k8s.gcr.io/kube-controller-manager:v1.17.17
k8s.gcr.io/kube-scheduler:v1.17.17
k8s.gcr.io/kube-proxy:v1.17.17
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.4.3-0
k8s.gcr.io/coredns:1.6.5
[root@k8s-master01 ~]#

编写初始化脚本

创建init.sh,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
# 下面的镜像应该去除"k8s.gcr.io"的前缀,版本换成kubeadm config images list命令获取到的版本
images=(
kube-apiserver:v1.17.5
kube-controller-manager:v1.17.5
kube-scheduler:v1.17.5
kube-proxy:v1.17.5
pause:3.1
etcd:3.4.3-0
coredns:1.6.5
)
for imageName in ${images[@]} ;
do
docker pull registry.cnhangzhou.aliyuncs.com/google_containers/$imageName
docker tag registry.cnhangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
docker rmi registry.cnhangzhou.aliyuncs.com/google_containers/$imageName
done

执行脚本

1
2
3
4
5
6
mkdir -p /data
cd /data
给脚本授权
chmod +x init.sh
执行脚本
./init.sh

保存镜像

这一步是为了简化其它节点的安装步骤,保存好镜像之后,其它服务器节点直接导入即可,不需要重新下载了

mster节点导出依赖

1
2
3
4
5
6
7
8
docker save -o k8s.1.17.5.tar \
k8s.gcr.io/kube-proxy:v1.17.5 \
k8s.gcr.io/kube-apiserver:v1.17.5 \
k8s.gcr.io/kube-controller-manager:v1.17.5 \
k8s.gcr.io/kube-scheduler:v1.17.5 \
k8s.gcr.io/coredns:1.6.5 \
k8s.gcr.io/etcd:3.4.3-0 \
k8s.gcr.io/pause:3.1 \

node节点依赖导出

1
2
3
docker save -o k8s.1.17.5.node.tar \
k8s.gcr.io/kube-proxy:v1.17.5 \
k8s.gcr.io/pause:3.1 \

导入镜像

导入master节点镜像

1
2
## master节点需要全部镜像
docker load -i k8s.1.17.5.tar

导入node节点镜像

1
2
## node节点需要kube-proxy:v1.17.5和pause:3.1,2个镜像
docker load -i k8s.1.17.5.node.tar

初始化集群

配置k8s集群网络

calico官网地址

1
2
3
4
5
6
7
8
9
官网下载地址:
https://docs.projectcalico.org/v3.14/manifests/calico.yaml
github地址:
https://github.com/projectcalico/calico
镜像下载:
docker pull calico/cni:v3.14.2
docker pull calico/pod2daemon-flexvol:v3.14.2
docker pull calico/node:v3.14.2
docker pull calico/kube-controllers:v3.14.2

初始化calico网络

命令

1
kubeadm init --apiserver-advertise-address=192.168.1.201 --kubernetes-version v1.17.5 --service-cidr=10.1.0.0/16 --pod-network-cidr=10.81.0.0/16

如果想重新初始化需要执行如下命令

1
2
3
4
5
6
##Master 节点和Work节点都需要执行:kubeadm reset
[root@k8s-master01 ~]# kubeadm reset
[reset] Reading configuration from the cluster...
[reset] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[reset] WARNING: Changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.
[reset] Are you sure you want to proceed? [y/N]:

注意:
kubeadm reset 执行后不会删除$HOME/.kube文件,执行rm -rf $HOME/.kube

初始化执行结果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
[root@k8s-master01 ~]# kubeadm init --apiserver-advertise-address=192.168.1.201 --kubernetes-version v1.17.5 --service-cidr=10.1.0.0/16 --pod-network-cidr=10.81.0.0/16
W0301 17:14:38.176171 43566 validation.go:28] Cannot validate kube-proxy config - no validator is available
W0301 17:14:38.176280 43566 validation.go:28] Cannot validate kubelet config - no validator is available
[init] Using Kubernetes version: v1.17.5
[preflight] Running pre-flight checks
[WARNING SystemVerification]: this Docker version is not on the list of validated versions: 20.10.1. Latest validated version: 19.03
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-master01 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.1.0.1 192.168.1.201]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8s-master01 localhost] and IPs [192.168.1.201 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8s-master01 localhost] and IPs [192.168.1.201 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
W0301 17:14:42.755403 43566 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[control-plane] Creating static Pod manifest for "kube-scheduler"
W0301 17:14:42.757179 43566 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 22.008317 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.17" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-master01 as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node k8s-master01 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: nk4m18.nkgdp55jjp63y4zn
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, 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

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.1.201:6443 --token nk4m18.nkgdp55jjp63y4zn \
--discovery-token-ca-cert-hash sha256:fe313df261948196e11da51dd6f0bd5d7f65ef1fd164fef55171bfbb3597f5d2

可以看到上边的执行结果最后一行,会输出密钥,node节点加入执行此命令即可

1
2
kubeadm join 192.168.1.201:6443 --token nk4m18.nkgdp55jjp63y4zn \
--discovery-token-ca-cert-hash sha256:fe313df261948196e11da51dd6f0bd5d7f65ef1fd164fef55171bfbb3597f5d2

执行配置

1
2
3
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

node节点加入集群

在node1和node2上执行如下命令,如下结果,则节点加入集群成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@k8s-node01 yum.repos.d]# kubeadm join 192.168.1.201:6443 --token nk4m18.nkgdp55jjp63y4zn \
> --discovery-token-ca-cert-hash sha256:fe313df261948196e11da51dd6f0bd5d7f65ef1fd164fef55171bfbb3597f5d2
W0301 17:21:04.062489 43250 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.
[preflight] Running pre-flight checks
[WARNING SystemVerification]: this Docker version is not on the list of validated versions: 20.10.1. Latest validated version: 19.03
[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'
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.17" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

[root@k8s-node01 yum.repos.d]#

其它问题

节点执行kubectl命令报错 The connection to the server localhost:8080 was refused

如果是下边报错

1
2
[root@k8s-master01 ~]# kubectl get nodes
The connection to the server localhost:8080 was refused - did you specify the right host or port?

首先检查,kubelet是否启动

1
[root@k8s-master01 ~]# systemctl status kubelet

如果正常启动,那执行如下命令即可

1
2
3
4
5
[root@k8s-master01 ~]# ll /etc/kubernetes/admin.conf
-rw-------. 1 root root 5453 Mar 1 17:14 /etc/kubernetes/admin.conf
[root@k8s-master01 ~]# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
[root@k8s-master01 ~]# source ~/.bash_profile

执行 kubectl get nodes 验证

如果是从节点问题,将/etc/kubernetes/admin.conf拷贝到从节点即可

1
2
3
scp  /etc/kubernetes/admin.conf root@192.168.1.202:/etc/kubernetes/
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source ~/.bash_profile

kubectl命令自动补全

1
2
echo "source <(kubectl completion bash)" >> ~/.bash_profile
source ~/.bash_profile

yum-key.gpg验证未通过

1
2
3
4
wget https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
wget https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
rpm --import yum-key.gpg
rpm --import rpm-package-key.gpg

K8S知识点

Kubernetes基础组件

一个 Kubernetes 集群包含 集群由一组被称作节点的机器组成。这些节点上运行 Kubernetes 所管理的 容器化应用。集群具有至少一个工作节点和至少一个主节点。 工作节点托管作为应用程序组件的 Pod 。主节点管理集群中的工作节点和 Pod 。多个主节点用于为集 群提供故障转移和高可用性。 本章概述交付正常运行的 Kubernetes 集群所需的各种组件。 这张图表展示了包含所有相互关联组件的 Kubernetes 集群。

控制平面组件(Control Plane Components)

控制平面的组件对集群做出全局决策(比如调度),以及检测和响应集群事件(例如,当不满足部署的 replicas 字段时,启动新的 pod)。 控制平面组件可以在集群中的任何节点上运行。然而,为了简单起见,设置脚本通常会在同一个计算机 上启动所有控制平面组件,并且不会在此计算机上运行用户容器。

kube-apiserver

主节点上负责提供 Kubernetes API 服务的组件;它是 Kubernetes 控制面的前端。

  1. kube-apiserver是Kubernetes最重要的核心组件之一
  2. 提供集群管理的REST API接口,包括认证授权,数据校验以及集群状态变更等
  3. 提供其他模块之间的数据交互和通信的枢纽(其他模块通过API Server查询或修改数据,只 有API Server才直接操作etcd)
  4. 生产环境可以为apiserver做LA或LB。在设计上考虑了水平扩缩的需要。 换言之,通过部署 多个实例可以实现扩缩。

etcd

etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。 Kubernetes 集群的 etcd 数据库通常需要有个备份计划。要了解 etcd 更深层次的信息,请参考 etcd 文 档。也可以使用外部的ETCD集群

  1. kubernetes需要存储很多东西,像它本身的节点信息,组件信息,还有通过kubernetes运行 的pod,deployment,service等等。都需要持久化。etcd就是它的数据中心。生产环境中为 了保证数据中心的高可用和数据的一致性,一般会部署最少三个节点。
  2. 这里只部署一个节点在master。etcd也可以部署在kubernetes每一个节点。组成etcd集群。
  3. 如果已经有etcd外部的服务,kubernetes直接使用外部etcd服务

kube-scheduler

主节点上的组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行。kube-scheduler负责分配调度Pod到集群内的节点上,它监听kube-apiserver,查询还未分 配Node的Pod,然后根据调度策略为这些Pod分配节点。

kube-controller-manager

在主节点上运行控制器的组件。Controller Manager由kube-controller-manager和cloud-controller-manager组成,是 Kubernetes的大脑,它通过apiserver监控整个集群的状态,并确保集群处于预期的工作状 态。 kube-controller-manager由一系列的控制器组成,像Replication Controller控制副 本,Node Controller节点控制,Deployment Controller管理deployment等等 cloudcontroller-manager在Kubernetes启用Cloud Provider的时候才需要,用来配合云服务提供 商的控制

kubectl

主节点上的组件, kubectl是Kubernetes的命令行工具,是Kubernetes用户和管理员必备的管理工具。 kubectl提供了大量的子命令,方便管理Kubernetes集群中的各种功能

Node 组件

节点组件在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 运行环境。

kubelet

一个在集群中每个节点上运行的代理。它保证容器都运行在 Pod 中。 一个在集群中每个工作节点上都运行一个kubelet服务进程,默认监听10250端口,接收并执 行master发来的指令,管理Pod及Pod中的容器。每个kubelet进程会在API Server上注册节 点自身信息,定期向master节点汇报节点的资源使用情况,并通过cAdvisor监控节点和容器 的资源。

kube-proxy

一个在集群中每台工作节点上都应该运行一个kube-proxy服务,它监听API server中service 和endpoint的变化情况,并通过iptables等来为服务配置负载均衡,是让我们的服务在集群 外可以被访问到的重要方式。

容器运行环境(Container Runtime)

容器运行环境是负责运行容器的软件。 Kubernetes 支持多个容器运行环境: Docker、 containerd、cri-o、 rktlet 以及任何实现 Kubernetes CRI (容器运行环境接口)。

插件(Addons)

插件使用 Kubernetes 资源 (DaemonSet, Deployment等) 实现集群功能。因为这些提供集群级别的功 能,所以插件的命名空间资源属于 kube-system 命名空间。 所选的插件如下所述:有关可用插件的扩展列表,请参见插件 (Addons)。

KUBE-DNS

kube-dns为Kubernetes集群提供命名服务,主要用来解析集群服务名和Pod的hostname。 目的是让pod可以通过名字访问到集群内服务。它通过添加A记录的方式实现名字和service 的解析。普通的service会解析到service-ip。headless service会解析到pod列表。

户界面(Dashboard)

Dashboard 是 Kubernetes 集群的通用基于 Web 的 UI。它使用户可以管理集群中运行的应用程序以及 集群本身并进行故障排除。

容器资源监控

容器资源监控将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中,并提供用于浏览这 些数据的界面。

集群层面日志

集群层面日志 机制负责将容器的日志数据保存到一个集中的日志存储中,该存储能够提供搜索和浏览接 口