文章内容非全部原创,有各位大佬的博客摘抄,也有自己踩坑的实践,主要记录一下整个学习和搭建过程,给有需要的同学。
1. K8S概述
有人说先看源码再搭建环境,有人说先玩一把再看源码,各有利弊,个人比较偏向实践性人格,所以我先准备搭建一个测试环境再看源码。
Master节点:
Master节点上面主要由四个模块组成,APIServer,schedule,controller-manager,etcd
APIServer: APIServer负责对外提供RESTful的kubernetes API的服务,它是系统管理指令的统一接口,任何对资源的增删该查都要交给APIServer处理后再交给etcd,如图,kubectl(kubernetes提供的客户端工具,该工具内部是对kubernetes API的调用)是直接和APIServer交互的。
schedule: schedule负责调度Pod到合适的Node上,如果把scheduler看成一个黑匣子,那么它的输入是pod和由多个Node组成的列表,输出是Pod和一个Node的绑定。 kubernetes目前提供了调度算法,同样也保留了接口。用户根据自己的需求定义自己的调度算法。
controller manager: 如果APIServer做的是前台的工作的话,那么controller manager就是负责后台的。每一个资源都对应一个控制器。而control manager就是负责管理这些控制器的,比如我们通过APIServer创建了一个Pod,当这个Pod创建成功后,APIServer的任务就算完成了。
etcd:etcd是一个高可用的键值存储系统,kubernetes使用它来存储各个资源的状态,从而实现了Restful的API。
Node节点:
每个Node节点主要由三个模板组成:kublet, kube-proxy
kube-proxy: 该模块实现了kubernetes中的服务发现和反向代理功能。kube-proxy支持TCP和UDP连接转发,默认基Round Robin算法将客户端流量转发到与service对应的一组后端pod。服务发现方面,kube-proxy使用etcd的watch机制监控集群中service和endpoint对象数据的动态变化,并且维护一个service到endpoint的映射关系,从而保证了后端pod的IP变化不会对访问者造成影响,另外,kube-proxy还支持session affinity。
kublet:kublet是Master在每个Node节点上面的agent,是Node节点上面最重要的模块,它负责维护和管理该Node上的所有容器,但是如果容器不是通过kubernetes创建的,它并不会管理。本质上,它负责使Pod的运行状态与期望的状态一致。
K8S核心组件:
etcd保存了整个集群的状态;
apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);
kube-proxy负责为Service提供cluster内部的服务发现和负载均衡。
实用的Add-ons:
kube-dns负责为整个集群提供DNS服务
Ingress Controller为服务提供外网入口
Heapster提供资源监控
Dashboard提供GUI
Federation提供跨可用区的集群
Fluentd-elasticsearch提供集群日志采集、存储与查询
2. kubeadm简介
kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,这不是一个单独的项目哦,我们在kubernetes源码里可以看到这个组件(kubernetes/cmd/kubeadm/)。kubeadm这个工具可以通过简单的kubeadm init和kubeadm join命令来创建一个kubernetes集群,kubeadm提供的其他命令都比较通俗易懂:
kubeadm init 启动一个master节点;
kubeadm join 启动一个node节点,加入master;
kubeadm upgrade 更新集群版本;
kubeadm config 从1.8.0版本开始已经用处不大,可以用来view一下配置;
kubeadm token 管理kubeadm join的token;
kubeadm reset 把kubeadm init或kubeadm join做的更改恢复原状;
kubeadm version打印版本信息;
kubeadm alpha预览一些alpha特性的命令。
3. 系统准备
我们先使用一台服务器安装,后面使用kubeadm join可以很轻松扩展。
3.1. 系统信息
内存:2G
CPU:2(K8S强制要求CPU核数大于2)
磁盘:32G
系统版本和内核版本:
cat /etc/redhat-release
#CentOS Linux release 7.7.1908 (Core)
uname -r
#3.10.0-1062.el7.x86_64
3.2. 配置selinux和firewalld
systemctl stop firewalld && systemctl disable firewalld
setenforce 0
vi /etc/selinux/config
SELINUX=disabled
3.3. 系统参数与内核模块
# 修改内核参数
cat < /etc/sysctl.d/k8s.conf
>net.bridge.bridge-nf-call-ip6tables = 1
>net.bridge.bridge-nf-call-iptables = 1
>EOF
sysctl --system
# 加载内核模块
modprobe br_netfilter
3.4. 配置yum源
# base repo
cd /etc/yum.repos.d
mv CentOS-Base.repo CentOS-Base.repo.bak
curl -o CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
sed -i 's/gpgcheck=1/gpgcheck=0/g' /etc/yum.repos.d/CentOS-Base.repo
# docker repo
curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# k8s repo
cat < /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 clean all
yum makecache
yum repolist
最终我们可以看到这些repo:
源标识 源名称 状态
!base/7/x86_64 CentOS-7 - Base - mirrors.aliyun.com 10,097
!docker-ce-stable/x86_64 Docker CE Stable - x86_64 59
!extras/7/x86_64 CentOS-7 - Extras - mirrors.aliyun.com 304
!kubernetes Kubernetes 409
!updates/7/x86_64 CentOS-7 - Updates - mirrors.aliyun.com 332
3.5. 禁用swap
swapoff -a && sysctl -w vm.swappiness=0
vi /etc/fstab
# 注释掉下面一行
# UUID=7bff6243-324c-4587-b550-55dc34018ebf swap swap defaults 0 0
也可以不禁用,在初始化安装时添加忽略swap检查参数并修改K8S配置文件,启动时忽略SWAP检查:
vi /etc/sysconfig/kubelet
KUBELET_ EXTRA_ ARGS="--fail-swap-on=false"
4. 安装docker
先看一下有哪些docker版本可用:
yum list docker-ce --showduplicates | sort -r
这里我选择18.06.3,所以我用的命令是:
yum install docker-ce-18.06.3.ce
启动docker:
systemctl enable docker --now
修改docker的daemon配置,可以避免后续初始化时的警告:
cat > /etc/docker/daemon.json <{
> "exec-opts": ["native.cgroupdriver=systemd"],
> "log-driver": "json-file",
> "log-opts": { "max-size": "100m" },
> "storage-driver": "overlay2"
>}
>EOF
mkdir -p /etc/systemd/system/docker.service.d
# 重启DOCKER
systemctl daemon-reload
systemctl restart docker
查看服务状态:
systemctl status docker
5. 安装kubeadm、kubelet和kubectl
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
启动kubelet:
systemctl enable --now kubelet
6. 镜像准备
为了解决国内普遍访问不到k8s.gcr.io的问题,我们从阿里云定制自己的容器镜像库,然后从定制的容器镜像库下载image,再给下载的镜像打tag。不会的同学可以查看我另外一篇博客《超详细教程使用Github和阿里云加速拉取国外Docker镜像》:
docker pull registry.cn-shanghai.aliyuncs.com/xxxxx/kube-apiserver:latest
docker pull registry.cn-shanghai.aliyuncs.com/xxxxx/kube-controller-manager:latest
docker pull registry.cn-shanghai.aliyuncs.com/xxxxx/kube-scheduler:latest
docker pull registry.cn-shanghai.aliyuncs.com/xxxxx/kube-proxy:latest
docker pull registry.cn-shanghai.aliyuncs.com/xxxxx/pause:latest
docker pull registry.cn-shanghai.aliyuncs.com/xxxxx/etcd:latest
docker pull registry.cn-shanghai.aliyuncs.com/xxxxx/coredns:latest
docker pull registry.cn-shanghai.aliyuncs.com/xxxxx/flannel:latest
docker pull registry.cn-shanghai.aliyuncs.com/xxxxx/dashboard:latest
docker pull registry.cn-shanghai.aliyuncs.com/xxxxx/metrics-scraper:latest
docker tag registry.cn-shanghai.aliyuncs.com/xxxxx/kube-apiserver:latest k8s.gcr.io/kube-apiserver:v1.16.1
docker tag registry.cn-shanghai.aliyuncs.com/xxxxx/kube-controller-manager:latest k8s.gcr.io/kube-controller-manager:v1.16.1
docker tag registry.cn-shanghai.aliyuncs.com/xxxxx/kube-scheduler:latest k8s.gcr.io/kube-scheduler:v1.16.1
docker tag registry.cn-shanghai.aliyuncs.com/xxxxx/kube-proxy:latest k8s.gcr.io/kube-proxy:v1.16.1
docker tag registry.cn-shanghai.aliyuncs.com/xxxxx/pause:latest k8s.gcr.io/pause:3.1
docker tag registry.cn-shanghai.aliyuncs.com/xxxxx/etcd:latest k8s.gcr.io/etcd:3.3.15-0
docker tag registry.cn-shanghai.aliyuncs.com/xxxxx/coredns:latest k8s.gcr.io/coredns:1.6.2
docker tag registry.cn-shanghai.aliyuncs.com/xxxxx/flannel:latest quay.io/coreos/flannel:v0.11.0-arm64
docker tag registry.cn-shanghai.aliyuncs.com/xxxxx/dashboard:latest kubernetesui/dashboard:v2.0.0-beta4
docker tag registry.cn-shanghai.aliyuncs.com/xxxxx/metrics-scraper:latest kubernetesui/metrics-scraper:v1.0.1
7. 安装k8s master
kubeadm init --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=Swap
kubeadm init的参数说明:
--apiserver-advertise-address string API Server将要广播的监听地址。如指定为 `0.0.0.0` 将使用缺省的网卡地址。
--apiserver-bind-port int32 缺省值: 6443 API Server绑定的端口
--apiserver-cert-extra-sans stringSlice 可选的额外提供的证书主题别名(SANs)用于指定API Server的服务器证书。可以是IP地址也可以是DNS名称。
--cert-dir string 缺省值: "/etc/kubernetes/pki" 证书的存储路径。
--config string kubeadm配置文件的路径。警告:配置文件的功能是实验性的。
--cri-socket string 缺省值: "/var/run/dockershim.sock" 指明要连接的CRI socket文件
--dry-run 不会应用任何改变;只会输出将要执行的操作。
--feature-gates string 键值对的集合,用来控制各种功能的开关。可选项有: Auditing=true|false (当前为ALPHA状态 - 缺省值=false) CoreDNS=true|false (缺省值=true) DynamicKubeletConfig=true|false (当前为BETA状态 - 缺省值=false)
-h, --help 获取init命令的帮助信息
--ignore-preflight-errors stringSlice 忽视检查项错误列表,•列表中的每一个检查项如发生错误将被展示输出为警告,而非错误。 例如: 'IsPrivilegedUser,Swap'. 如填写为 'all' 则将忽视所有的检查项错误。
--kubernetes-version string 缺省值: "stable-1" 为control plane选择一个特定的Kubernetes版本。
--node-name string 指定节点的名称。
--pod-network-cidr string 指明pod网络可以使用的IP地址段。 如果设置了这个参数,control plane将会为每一个节点自动分配CIDRs。
--service-cidr string 缺省值: "10.96.0.0/12" 为service的虚拟IP地址另外指定IP地址段
--service-dns-domain string 缺省值: "cluster.local" 为services另外指定域名, 例如: "myorg.internal".
--skip-token-print 不打印出由 `kubeadm init` 命令生成的默认令牌。
--token string 这个令牌用于建立主从节点间的双向受信链接。格式为 [a-z0-9]{6}\.[a-z0-9]{16} - 示例: abcdef.0123456789abcdef
--token-ttl duration 缺省值: 24h0m0s 令牌被自动删除前的可用时长 (示例: 1s, 2m, 3h). 如果设置为 '0', 令牌将永不过期。
如果遇到报错,对着错误信息修正一下,错误都报的很明白。比如:没有关闭swap;系统cpu不够;网络不通;镜像下载失败等等。执行完init命令后,会看到类似如下的输出:
Your Kubernetes master 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/
You can now join any number of machines by running the following on each node
as root:
kubeadm join 10.211.55.18:6443 --token di2xhw.d2578vsvbn2v8n4v --discovery-token-ca-cert-hash \sha256:a3ed7b53f4041ecbbdd8fa5d460856a290751784d4debffdf57b71b064be998e
上面输出告诉我们还需要做一些工作:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
稍等一会,应该可以看到node状态变成ready:
kubectl get node
如果没有ready可以查看一下pod是否正常,一般问题都是下载的镜像有问题。
kubectl get pod -n kube-system
全部ready以后,再看一下核心组件状态。
kubectl get cs
最后注意到dev1这个node上有一个Taint:
kubectl describe node dev1 | grep Taints
#Taints: node-role.kubernetes.io/master:NoSchedule
默认master节点是不跑业务pod的,我们暂时只有一个node,所以先去掉这个Taint:
kubectl taint node dev1 node-role.kubernetes.io/master-
#node/dev1 untainted
kubectl describe node kube-master | grep Taints
#Taints:
8. 用kubeadm部署node,把其加入master,在各个node上执行上方生成的join命令。
kubeadm join 10.211.55.18:6443 --token di2xhw.d2578vsvbn2v8n4v --discovery-token-ca-cert-hash sha256:a3ed7b53f4041ecbbdd8fa5d460856a290751784d4debffdf57b71b064be998e
9、安装网络插件
安装网络插件需要注意保证仓库中已经有相关的镜像,或者网络可以访问quay.io等国外网站。通过查找yml文件可以知道需要什么版本的镜像。我使用的Flannel:
kubectl create -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
10、安装Dashboard
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta4/aio/deploy/recommended.yaml
vi recommended.yaml
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort # 改成NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 31001 # 指定nodePort端口
selector:
k8s-app: kubernetes-dashboard
kubectl create -f recommended.yaml
如果忘记TOKEN,可以使用以下命令
kubectl describe secrets -n kubernetes-dashboard $(kubectl -n kubernetes-dashboard get secret | awk '/kubernetes-dashboard/{print $1}')
11、猜到的坑
dashboard登录
kubectl create serviceaccount cluster-admin-dashboard-sa
kubectl create clusterrolebinding cluster-admin-dashboard-sa \
--clusterrole=cluster-admin \
--serviceaccount=default:cluster-admin-dashboard-sa
kubectl get secret | grep cluster-admin-dashboard-sa
kubectl describe secret cluster-admin-dashboard-sa-token-6xm8l
删除 dev3 节点
kubectl drain dev3 --delete-local-data --force --ignore-daemonsets
kubectl delete node dev3