本文内容参考《kuberneters进阶实战》/马哥的新书/推荐
部署前的准备
主机名称解析
分布式系统环境中的多主机通信通常基于主机名称进行,这在IP地址存在变化的可能性时为主机提供了固定的访问入口,因此一般需要有专用的DNS服务负责解决各节点主机名。不过,考虑到此处部署的是测试集群,因此为了降低系统的复杂度,这里将采用基于hosts的文件进行主机名称解析
master节点和nodes都需要修改hosts文件
192.168.18.64 master
192.168.18.65 node1
192.168.18.66 node2
192.168.18.67 node3
主机时间同步
如果使用的是云服务器,一般云厂商都已经设置好了
关闭防火墙
各Node运行的kube-proxy组件均要借助iptables或ipvs构建Service资源对象,该资源对象是Kubernetes的核心资源之一。出于简化问题复杂度之需,这里需要事先关闭所有主机之上的iptables或firewalld服务
# systemctl stop iptables.service
# systemctl disable iptables.service
关闭并仅用SELinux
禁用swap设备 (可选)
kubeadm默认会预先检查当前主机是否禁用了Swap设备,并在未禁用时强制终止部署过程。因此,在主机内存资源充裕的条件下,需要禁用所有的Swap设备。
# 关闭swap设备
swapoff -a
然后编辑/etc/fstab
配置文件,另外部署时也可以不禁用swap设备,可在使用kubeadm命令时额外使用相关命令忽略检查错误
启用ipvs内核模块 (可选)
Kubernetes1.11之后的版本默认支持使用ipvs代理模式的Service资源,但它依赖于ipvs相关的内核模块,而这些模块默认不会自动载入。因此,这里选择创建载入内核模块相关的脚本文件/etc/sysconfig/modules/ipvs.modules,设定于系统引导时自动载入的ipvs相关的内核模块,以支持使用ipvs代理模式的Service资源。文件内容如下:
#!/bin/bash
ipvs_mods_dir="/usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs"
for i in $(ls $ipvs_mods_dir | grep -o "^[^.] *"); do
/sbin/modinfo -F filename $i &> /dev/null
if [ $ -eq 0 ]; then
/sbin/ modprobe $i
fi
done
然后修改文件权限,并手动为当前系统环境加载内核
chmod +x /etc/sysconfig/modules/ipvs.modules
/etc/sysconfig/modules/ipvs.modules
镜像下载
为啥要将镜像单独准备,因为这个门槛越不过去,你会遇到很多莫名其妙的问题(对于新手来讲)
以下是必须的镜像和正在运行的docker容器
[root@master ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
k8s.gcr.io/kube-proxy v1.13.1 fdb321fd30a0 4 weeks ago 80.2MB
registry.cn-hangzhou.aliyuncs.com/mmyk8s/kube-proxy-amd64 v1.13.1 fdb321fd30a0 4 weeks ago 80.2MB
k8s.gcr.io/kube-apiserver v1.13.1 40a63db91ef8 4 weeks ago 181MB
registry.cn-hangzhou.aliyuncs.com/mmyk8s/kube-apiserver-amd64 v1.13.1 40a63db91ef8 4 weeks ago 181MB
k8s.gcr.io/kube-scheduler v1.13.1 ab81d7360408 4 weeks ago 79.6MB
registry.cn-hangzhou.aliyuncs.com/mmyk8s/kube-scheduler-amd64 v1.13.1 ab81d7360408 4 weeks ago 79.6MB
k8s.gcr.io/kube-controller-manager v1.13.1 26e6f1db2a52 4 weeks ago 146MB
registry.cn-hangzhou.aliyuncs.com/mmyk8s/kube-controller-manager-amd64 v1.13.1 26e6f1db2a52 4 weeks ago 146MB
k8s.gcr.io/coredns 1.2.6 f59dcacceff4 2 months ago 40MB
registry.cn-hangzhou.aliyuncs.com/mmyk8s/coredns 1.2.6 f59dcacceff4 2 months ago 40MB
registry.cn-hangzhou.aliyuncs.com/mmyk8s/etcd-amd64 3.2.24 3cab8e1b9802 3 months ago 220MB
k8s.gcr.io/etcd 3.2.24 3cab8e1b9802 3 months ago 220MB
quay.io/coreos/flannel v0.10.0-amd64 f0fad859c909 11 months ago 44.6MB
registry.cn-hangzhou.aliyuncs.com/mmyk8s/flannel v0.10.0-amd64 f0fad859c909 11 months ago 44.6MB
k8s.gcr.io/pause 3.1 da86e6ba6ca1 12 months ago 742kB
registry.cn-hangzhou.aliyuncs.com/mmyk8s/pause 3.1 da86e6ba6ca1 12 months ago 742kB
[root@master ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
36d09d27fd26 f59dcacceff4 "/coredns -conf /etc…" 8 hours ago Up 8 hours k8s_coredns_coredns-86c58d9df4-cm4pm_kube-system_6e51adc0-14c0-11e9-ac10-000c29bed493_0
05bb6e3b85e9 f59dcacceff4 "/coredns -conf /etc…" 8 hours ago Up 8 hours k8s_coredns_coredns-86c58d9df4-g2mf4_kube-system_6e50f388-14c0-11e9-ac10-000c29bed493_0
51b284840974 k8s.gcr.io/pause:3.1 "/pause" 8 hours ago Up 8 hours k8s_POD_coredns-86c58d9df4-cm4pm_kube-system_6e51adc0-14c0-11e9-ac10-000c29bed493_0
b3e5b80bb640 k8s.gcr.io/pause:3.1 "/pause" 8 hours ago Up 8 hours k8s_POD_coredns-86c58d9df4-g2mf4_kube-system_6e50f388-14c0-11e9-ac10-000c29bed493_0
5f50cad2717e f0fad859c909 "/opt/bin/flanneld -…" 8 hours ago Up 8 hours k8s_kube-flannel_kube-flannel-ds-amd64-7xh79_kube-system_ad897b0d-14c0-11e9-ac10-000c29bed493_0
73bb596c654e 3cab8e1b9802 "etcd --advertise-cl…" 23 hours ago Up 23 hours k8s_etcd_etcd-master_kube-system_54caa73c3a366810eb1982ce52213834_1
d5d71dfc331c ab81d7360408 "kube-scheduler --ad…" 23 hours ago Up 23 hours k8s_kube-scheduler_kube-scheduler-master_kube-system_44b569a35761491825f4e7253fbf0543_1
7ff702474352 40a63db91ef8 "kube-apiserver --au…" 23 hours ago Up 23 hours k8s_kube-apiserver_kube-apiserver-master_kube-system_4e3289b38af39fb55c00956ffb875c26_1
590cb4078099 26e6f1db2a52 "kube-controller-man…" 23 hours ago Up 23 hours k8s_kube-controller-manager_kube-controller-manager-master_kube-system_7d0a1ff3545bbc890a67b0d02dc0f191_1
c22bcc9f6903 fdb321fd30a0 "/usr/local/bin/kube…" 23 hours ago Up 23 hours k8s_kube-proxy_kube-proxy-m8wsf_kube-system_b8572ad6-14bf-11e9-ac10-000c29bed493_1
8d63b75de565 k8s.gcr.io/pause:3.1 "/pause" 23 hours ago Up 23 hours k8s_POD_kube-flannel-ds-amd64-7xh79_kube-system_ad897b0d-14c0-11e9-ac10-000c29bed493_1
fe0b44fe8c09 k8s.gcr.io/pause:3.1 "/pause" 23 hours ago Up 23 hours k8s_POD_kube-proxy-m8wsf_kube-system_b8572ad6-14bf-11e9-ac10-000c29bed493_1
729321ce5699 k8s.gcr.io/pause:3.1 "/pause" 23 hours ago Up 23 hours k8s_POD_kube-scheduler-master_kube-system_44b569a35761491825f4e7253fbf0543_1
b635e5dd38d0 k8s.gcr.io/pause:3.1 "/pause" 23 hours ago Up 23 hours k8s_POD_etcd-master_kube-system_54caa73c3a366810eb1982ce52213834_1
85502af97ba9 k8s.gcr.io/pause:3.1 "/pause" 23 hours ago Up 23 hours k8s_POD_kube-apiserver-master_kube-system_4e3289b38af39fb55c00956ffb875c26_2
240c427dc4dc k8s.gcr.io/pause:3.1 "/pause" 23 hours ago Up 23 hours k8s_POD_kube-controller-manager-master_kube-system_7d0a1ff3545bbc890a67b0d02dc0f191_1
在后面初始化kuberneters集群的时候,依赖的这些镜像默认是从k8s.gcr.io去pull镜像,但是在国内是无法访问的
我们可以通过阿里云或者腾讯云先将镜像构建在阿里的镜像仓库中,然后再tag为需要的镜像标签
阿里云上自定义镜像仓库
仓库中自定义的构建信息,这里指定了dockerfile文件的地址在github上
这里为github上dockerfile的内容,以官方镜像为基础镜像构建后存在阿里的镜像仓库中
所有镜像构建完成后,通过命令pull到本地,打tag即可使用
写了一个脚本,避免重复的工作
#!/bin/bash
set -e
IMAGE_URL=registry.cn-hangzhou.aliyuncs.com/
IMAGE_URL_TAG=k8s.gcr.io
# 这里为个人的阿里云镜像仓库账户
USER=
PASSWD=
REGNAME=
docker login $IMAGE_URL -u $USER -p $PASSWD
# 初始化集群需要的镜像
#IMAGE_LIST=(coredns:1.2.6 etcd-amd64:3.2.24 kube-apiserver-amd64:v1.13.1 kube-controller-manager-amd64:v1.13.1 kube-proxy-amd64:v1.13.1 kube-scheduler-amd64:v1.13.1 pause:3.1)
for i in coredns:1.2.6 etcd-amd64:3.2.24 kube-apiserver-amd64:v1.13.1 kube-controller-manager-amd64:v1.13.1 kube-proxy-amd64:v1.13.1 kube-scheduler-amd64:v1.13.1 pause:3.1
do
docker pull $IMAGE_URL$REGNAME/$i
echo "$i下载成功"
done
# flannel插件镜像
docker pull registry.cn-hangzhou.aliyuncs.com/mmyk8s/flannel:v0.10.0-amd64
docker tag registry.cn-hangzhou.aliyuncs.com/mmyk8s/kube-proxy-amd64:v1.13.1 k8s.gcr.io/kube-proxy:v1.13.1
docker tag registry.cn-hangzhou.aliyuncs.com/mmyk8s/kube-apiserver-amd64:v1.13.1 k8s.gcr.io/kube-apiserver:v1.13.1
docker tag registry.cn-hangzhou.aliyuncs.com/mmyk8s/kube-controller-manager-amd64:v1.13.1 k8s.gcr.io/kube-controller-manager:v1.13.1
docker tag registry.cn-hangzhou.aliyuncs.com/mmyk8s/kube-scheduler-amd64:v1.13.1 k8s.gcr.io/kube-scheduler:v1.13.1
docker tag registry.cn-hangzhou.aliyuncs.com/mmyk8s/kube-scheduler-amd64:v1.13.1 k8s.gcr.io/kube-scheduler:v1.13.1
docker tag registry.cn-hangzhou.aliyuncs.com/mmyk8s/coredns:1.2.6 k8s.gcr.io/coredns:1.2.6
docker tag registry.cn-hangzhou.aliyuncs.com/mmyk8s/etcd-amd64:3.2.24 k8s.gcr.io/etcd:3.2.24
docker tag registry.cn-hangzhou.aliyuncs.com/mmyk8s/flannel:v0.10.0-amd64 quay.io/coreos/flannel:v0.10.0-amd64
docker tag registry.cn-hangzhou.aliyuncs.com/mmyk8s/pause:3.1 k8s.gcr.io/pause:3.1
echo “标签修改成功”
每个节点都需要这些镜像!
还有一种方法没用实践过,在下文中初始化集群使用的是第一种方式,在第二种方式中,imageRepository: k8s.gcr.io
指定了镜像仓库地址,是否可以改为国内地址或者自己的私有仓库地址,这样就不用tag了。
部署kuberneters集群
kubeadm是用于快速构建Kubernetes集群的工具,随着Kubernetes的发行版本而提供,使用它构建集群时,大致可分为如下几步:
- 在Master及各Node安装Docker、kubelet及kubeadm,并以系统守护进程的方式启动Docker和kubelet服务。
- 在Master节点上通过kubeadminit命令进行集群初始化。
- 各Node通过kubeadmjoin命令加入初始化完成的集群中。
- 在集群上部署网络附件,如flannel或Calico等以提供Service网络及Pod网络。
为了简化部署过程,kubeadm使用一组固定的目录及文件路径存储相关的配置及数据文件,其中/etc/kubernetes目录是所有文件或目录的统一存储目录。它使用/etc/kubernetes/manifests目录存储各静态Pod资源的配置清单,用到的文件有etcd.yaml、kube-apiserver.yaml、kube-controller-manager.yaml和kube-scheduler.yaml四个,它们的作用基本能够见名知义。另外,/etc/kubernetes/目录中还会为Kubernetes的多个组件存储专用的kubeconfig文件,如kubelet.conf、controller-manager.conf、scheduler.conf和admin.conf等,它们分别为相关的组件提供接入APIServer的认证信息等。此外,它还会在/etc/kubernetes/pki目录中存储若干私钥和证书文件
设定容器运行的环境
这里基本就是docker的安装和一些简单的配置
安装kubelet和kubeadm
kubelet是运行于集群中每个节点之上的Kubernetes代理程序,它的核心功能在于通过APIServer获取调度至自身运行的Pod资源的PodSpec并依之运行Pod对象。事实上,以自托管方式部署的Kubernetes集群,除了kubelet和Docker之外的所有组件均以Pod对象的形式运行
设定用于安装kubelet、kubeadm和kubectl等组件的yum仓库,编辑配置文件/etc/yum.repos.d/kubernetes.repo
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
yum install kubelet kubeadm kubectl
配置kubelet
Kubernetes自1.8版本起强制要求关闭系统上的交换分区(Swap),否则kubelet将无法启动。当然,用户也可以通过将kubelet的启动参数“--fail-swap-on”设置为“false”忽略此限制,尤其是系统上运行有其他重要进程且系统内存资源稍嫌不足时建议保留交换分区。
编辑kubelet的配置文件/etc/sysconfig/kubelet,设置其配置参数如下,以忽略禁止使用Swap的限制:
KUBELET_ EXTRA_ ARGS="--fail-swap-on=false"
待配置文件修改完成后,需要设定kubelet服务开机自动启动,这也是kubeadm的强制要求:
systemctl enable kubelet.service
以上部分的配置需要在集群所有机器配置,install kubelet kubeadm kubectl是安装集群的基本条件,这些服务的安装使用基于docker,环境的配置,例如防火墙等是保证初始化集群等的最基本条件
master节点初始化集群
在Master节点上执行“kubeadminit”命令进行集群初始化。kubeadminit命令支持两种初始化方式,一是通过命令行选项传递关键的参数设定,另一个是基于yaml格式的专用配置文件设定更详细的配置参数
第一种方式:
kubeadm init --kubernetes-version=v1.13.1 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --apiserver-advertise-address=0.0.0.0 --ignore-preflight-errors=Swap
--kubernetes-version:正在使用的Kubernetes程序组件的版本号,需要与kubelet的版本号相同。
--pod-network-cidr:Pod网络的地址范围,其值为CIDR格式的网络地址;使用flannel网络插件时,其默认地址为10.244.0.0/16。
--service-cidr:Service的网络地址范围,其值为CIDR格式的网络地址,默认地址为10.96.0.0/12。
--apiserver-advertise-address:APIserver通告给其他组件的IP地址,一般应该为Master节点的IP地址,0.0.0.0表示节点上所有可用的地址。
--ignore-preflight-errors:忽略哪些运行时的错误信息,其值为Swap时,表示忽略因swap未关闭而导致的错误。
第二种方式:
kubeadminit也配置文件加载配置,以定制更丰富的部署选项。以下是符合前述命令设定方式的使用示例,不过,它明确定义了kubeProxy的模式为ipvs,并支持通过修改imageRepository的值来修改获取系统镜像时使用的镜像仓库。
apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.13.1
api:
advertiseAddress: 192.168.18.64
bindPort: 6443
controlPlaneEndpoint: ""
imageRepository: k8s.gcr.io
kubeProxy:
config:
mode: "ipvs"
ipvs:
ExcludeCIDRs: null
minSyncPeriod: 0s
scheduler: ""
syncPeriod: 30s
kubeletConfiguration:
baseConfig:
cgroupDriver: cgroupfs
clusterDNS:
-10.96.0.10
clusterDomain: cluster.local
failSwapOn: false
resolvConf: /etc/resolv.conf
staticPodPath: /etc/kubernetes/manifests
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
将以上配置保存为kubedm-config.yaml
kubeadm init --config kubeadm-config.yaml --ignore-preflight-errors=Swap
成功后会生成node节点加入集群的命令
kubeadm join 192.168.18.64:6443 --token 4mvox7.5l6fgyyqo761yxyf --discovery-token-ca-cert-hash sha256:1cd687ae5837b85a48f9ca93873aa67b30d29b1584db3b1f2ede946506735035
完成集群部署还需要执行三类操作:设定kubectl的配置文件、部署网络附件以及将各Node加入集群。下面就来讲解如何进行这三步操作。
设定kubectl的配置文件根据输出的命令执行就可以
至此为止,一个KubernetesMaster节点已经基本配置完成。接下来即可通过APIServer来验证其各组件的运行是否正常。kubectl有着众多子命令,其中“getcompontsstatuses”即能显示出集群组件当前的状态,也可使用其简写格式“get cs”:
[root@master ~]# kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health": "true"}
若上面命令结果的STATUS字段为“Healthy”,则表示组件处于健康运行状态,否则需要检查其错误所在,必要时可使用“kubeadm reset”命令重置之后重新进行集群初始化。
另外,使用“kubectl get nodes”命令能够获取集群节点的相关状态信息,显示了Master节点的状态为“NotReady”(未就绪),这是因为集群中尚未安装网络插件所致,执行完后面的其他步骤后它即自行转为“Ready”:
注: 此处为已经安装fannel网络插件后的结果
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 21h v1.13.1
node1 Ready <none> 63m v1.13.1
master节点部署网络插件fannel
基于kubeadm部署时,flannel同样运行为Kubernetes集群的附件,以Pod的形式部署运行于每个集群节点上以接受Kubernetes集群管理。
事实上,也可以直接将flannel程序包安装并以守护进程的方式运行于集群节点上,即以非托管的方式运行。部署方式既可以是获取其资源配置清单于本地而后部署于集群中,也可以直接在线进行应用部署。
部署命令是“kubectlapply”或“kubectlcreate”,例如,下面的命令将直接使用在线的配置清单进行flannel部署:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
参考 https://github.com/coreos/flannel
至此master节点就完成了!
node节点加入
Master各组件运行正常后即可将各Node添加至集群中。配置节点时,需要事先参考前面“设置容器运行环境”和“设定Kubernetes集群节点”两节中的配置过程设置好Node主机,而后即可在Node主机上使用“kubeadmjoin”命令将其加入集群中。
kubeadm join 192.168.18.64:6443 --token 4mvox7.5l6fgyyqo761yxyf --discovery-token-ca-cert-hash sha256:1cd687ae5837b85a48f9ca93873aa67b30d29b1584db3b1f2ede946506735035
提供给APIServer的bootstraptoken认证完成后,kubeadmjoin命令会为后续Master与Node组件间的双向ssl/tls认证生成私钥及证书签署请求,并由Node在首次加入集群时提交给Master端的CA进行签署。
默认情况下,kubeadm配置kube-apiserver启用了bootstrapTLS功能,并支持证书的自动签署。于是,kubelet及kube-proxy等组件的相关私钥和证书文件在命令执行结束后便可自动生成,它们默认保存于/var/lib/kubelet/pki目录中。
在每个节点上重复上述步骤就能够将其加入集群中。所有节点加入完成后,即可使用“kubectlgetnodes”命令验证集群的节点状态,包括各节点的名称、状态就绪与否、角色(是否为节点Master)、加入集群的时长以及程序的版本等信息:
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 21h v1.13.1
node1 Ready <none> 79m v1.13.1
重新生成用于节点加入集群的认证命令
如果忘记了节点加入集群的认证命令,需要在master节点通过kubeadm tokem list
获取认证令牌,再生成验证CA公钥的哈希值
[root@master ~]# kubeadm token list
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
4mvox7.5l6fgyyqo761yxyf 12m 2019-01-11T18:08:33+08:00 authentication,signing The default bootstrap token generated by 'kubeadm init'. system:bootstrappers:kubeadm:default-node-token
[root@master ~]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
1cd687ae5837b85a48f9ca93873aa67b30d29b1584db3b1f2ede946506735035
将上述命令生成的值合为如下命令:
kubeadm join 192.168.18.64:6443 --token TOKEN --discover-token-ca-cert-hash sha256:HASH
即为
kubeadm join 192.168.18.64:6443 --token 4mvox7.5l6fgyyqo761yxyf --discover-token-ca-cert-hash sha256:1cd687ae5837b85a48f9ca93873aa67b30d29b1584db3b1f2ede946506735035
一些坑
[root@node2 ~]# kubeadm join 192.168.18.64:6443 --token 4mvox7.5l6fgyyqo761yxyf --discovery-token-ca-cert-hash sha256:1cd687ae5837b85a48f9ca93873aa67b30d29b1584db3b1f2ede946506735035
[preflight] Running pre-flight checks
[WARNING SystemVerification]: this Docker version is not on the list of validated versions: 18.09.0. Latest validated version: 18.06
[WARNING Service-Kubelet]: kubelet service is not enabled, please run 'systemctl enable kubelet.service'
[preflight] Some fatal errors occurred:
[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1
[ERROR FileContent--proc-sys-net-ipv4-ip_forward]: /proc/sys/net/ipv4/ip_forward contents are not set to 1
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
node节点加入集群时
第一个warnning是版本验证问题,不用管
第二个warnning前面说到过,kubectl开机自启动是kubeadm的强制要求
error问题
[root@node2 ~]# vim /proc/sys/net/bridge/bridge-nf-call-iptables
[root@node2 ~]# vim /etc/sysctl.conf
[root@node2 ~]# echo "1" >/proc/sys/net/ipv4/ip_forward
[root@node2 ~]# sysctl -p /etc/sysctl.conf