最后买了一门课程,系统的学习一下Kubernetes。
根据课程,同时也参考了网上其他的资料,安装配置了一个本地K8S集群,这里记录一下。
课程中使用K8S为1.11.1版本,看了下课程发布时间:2018-09-17,已经有一年多了,现在(2020-02)K8S最新版本为1.17.3。考虑课程学习的一致性,本打算安装1.11.1版,可惜在Ubuntu和CentOS中都没有找到kubeadm的1.11.1版本,无奈这里安装了最新版本。
结过一番折腾总算安装成功,总结+改良操作过程之后发现得此记录。按此记录的操作流程执行比较顺利,不用怎么关心国内的网络限制,可以一气呵成的搭建一套本地学习&测试用的集群(而且是软件仓库中提供的最后版本),配合Rook
项目,Ceph
存储也加上了。好东西不能一人独赏,特拿来与诸君分享。
安装环境
我是在自己的MBP 2016上启动了三个Fusion虚拟机作为K8S节点的,我的MBP有16G内存,以此为前提,各节点推荐配置如下:
k8s node | CPU cores | RAM | Disk size | Hostname | IP |
---|---|---|---|---|---|
master | 4 | 4G | 128G | k8s-master | 172.16.151.10 |
worker | 2 | 4G | 128G | k8s-worker1 | 172.16.151.11 |
worker | 2 | 4G | 128G | k8s-worker2 | 172.16.151.12 |
其中 master 至少要3G内存,2 CPU core(按我的MBP 16的CPU性能来说),再少master节点就会比较卡顿;worker节点可以减少内存到2G,在Pod数量比较少的情况下影响不大(就我目前的学习进度来说,还没有卡过)。磁盘空间按课程内容,要30G以上,这里因为是动态分配的虚拟磁盘, 我就一步到位加到128G了。
网络模式使用自定义模式:相当于host-only + NAT转发,将主机加入虚拟网络。虚拟网络网关和DHCP服务器为172.16.151.2,主机在虚拟网络中IP为172.16.151.1
注意在为虚拟机安装系统时,配置网络为ipv4/manual/static以固定IP地址。
虚拟机的操作系统选用了Ubuntu 18.04 X64系统,安装过程就不赘述了。
配置各节点环境,准备安装
为了方便后续操作,先在本地工作目录(如~/k8s-install
) 中为各节点创建IP文件
echo '172.16.151.10' > ip-m1
echo '172.16.151.11' > ip-w1
echo '172.16.151.12' > ip-w2
使用这些IP文件我们就可以以如下方式批量操作这些节点了:
for IP_FILE in $(ls ip-*); do
IP=$(cat $IP_FILE)
echo "IP of $IP_FILE: $IP"
#do anything with $IP here
unset IP
done && unset IP_FILE
之后我为各虚拟机节点执行了以下配置:
配置root ssh登录
因为Ubuntu默认禁止root用户使用用户名密码登录,我们只能第一步配置ssh key登录安装系统时创建的普通用户。
for IP_FILE in $(ls ip-*); do
IP=$(cat $IP_FILE)
ssh-copy-id -i ~/.ssh/rsa.pub ubuntu@$IP # 此操作需要输入虚拟机用户ubuntu的密码
ssh ubuntu@$IP # 以用户ubuntu的身份免密登录到虚拟机上,执行后面说明的操作
unset IP
done && unset IP_FILE
在各节点上登录ubuntu执行的操作:
sudo mkdir -p /root/.ssh && sudo cp ~/.ssh/authorized_keys /root/.ssh/
配置apt源
为了加快下载速度,这时使用阿里云的kubernetes、docker-ce镜像仓库。
for IP_FILE in `ls ip-*`; do
IP=`cat $IP_FILE`
ssh root@$IP "
apt update -y && apt upgrade -y && apt autoremove -y && apt install -y apt-transport-https ca-certificates curl software-properties-common
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat </etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
cat </etc/apt/sources.list.d/docker-ce.list
deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \$(lsb_release -cs) stable
EOF
apt update -y
"
unset IP
done && unset IP_FILE
安装
安装 Docker CE
for IP_FILE in `ls ip-*`; do
IP=`cat $IP_FILE`
ssh root@$IP "
apt -y install docker-ce
systemctl enable docker
cat > /etc/docker/daemon.json <
安装 kubeadm 工具
for IP_FILE in `ls ip-*`; do
IP=`cat $IP_FILE`
ssh root@$IP "
apt install -y kubeadm # 这里会依赖安装 kubelet、kubectl
systemctl enable kubelet
systemctl start kubelet
"
unset IP
done && unset IP_FILE
准备k8s镜像
课程要求我们准备可以访问gcr.io的环境,但由于众所周知的原因,身处国内无法直接访问gcr.io镜像仓库,这里使用Azure 中国镜像的方案变通解决。
for IP_FILE in `ls ip-*`; do
IP=`cat $IP_FILE`
ssh root@$IP "
kubeadm config images list 2>/dev/null|grep ^k8s\\.gcr\\.io|awk -F '/' '{print \$2}' - | while read imageName ; do
docker pull gcr.azk8s.cn/google_containers/\$imageName
docker tag gcr.azk8s.cn/google_containers/\$imageName k8s.gcr.io/\$imageName
docker rmi gcr.azk8s.cn/google_containers/\$imageName
done
"
unset IP
done && unset IP_FILE
解释下上面在节点上执行的脚本:
- kubeadm config image list 会列出k8s必须的镜像。因为无法访问 grc.io ,该指令会输出一行错误到 stderr,使用 2>/dev/null 清除之
- 输出的镜像tag列表,经过 grep 和 awk 取出 imageName,如 k8s.gcr.io/pause:3.1 取出 imageName 为 pause:3.1
- 对每行取出 imageName 通过 Azure中国镜像代理pull、tag获得最终需要的docker image
禁用linux swap
kubernetes要求禁用linux swap,否则后继执行kubeadm指令时,preflight检查会失败
for IP_FILE in `ls ip-*`; do
IP=`cat $IP_FILE`
ssh root@$IP "
swapoff -a
sysctl -w vm.swappiness=0
cp /etc/fstab /etc/fstab.origin
sed -i '/swap/s/^/#/' /etc/fstab
"
unset IP
done && unset IP_FILE
使用 kubeadm init 配置 master 节点
ssh root@`cat ip-m1` " kubeadm init --token-ttl 0 " # 使用--token-ttl 0是为了之后方便添加节点,kubeadm不适合用于生产环境部署,测试/开发/学习用环境 token 永不过期应该也没多大问题,如果要用 kubeadm 部署生产环境,不要设置为永不过期
上述操作最后会输出一行kubeadm join
指令,将这条指令保存为本地工作目录的kubeadm-join.sh
文件备用
到此,虽然kubernetes集群还没有完成安装,但已经可以通过kubectl进行交互了。
下载 kubectl 配置文件
下面的操作假设你本地默认位置没有其他kubernetes集群的kubeconfig配置文件,如果有请自行备份。当然也有方法进行合并,合并的方法我会再另外的文章中说明。
mkdir -p ~/.kube
scp root@`cat ip-m1`:/etc/kubernetes/admin.conf ~/.kube/config
安装 CNI 插件
现在,使用kubectl
已经能和k8s集群交互了,但通过kubectl get nodes
命令可以发现,现在唯一的节点k8s-master
是NotReady
的状态。这是因为我们没有安装CNI容器网络插件。
Installing Addons页面列出了一些可用的插件,其中“Networking and Network Policy”小节列出了网络插件,这里我们按课程内容选用了“Weave Net”插件。
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
等待一段时间,kubectl get nodes
命令就会返回k8s-master
节点是Ready
状态了。
使用 kubeadm join 配置 worker 节点
for IP_FILE in `ls ip-w*`; do
IP=`cat $IP_FILE`
ssh root@$IP < kubeadm-join.sh
unset IP
done && unset IP_FILE
等待各worker节点的Pod都启动之后,k8s集群就安装完成了。
配置&增强
在安装完集群之后,我们还需要一些配置:安装dashboard、部署存储插件等
删除 master 上的 Taint
默认情况下,master节点上会带有一个Taint
:node-role.kubernetes.io/master:NoSchedule
。如果新Pod没有对应的Toleration
规则,就不会被kubernetes调度到master节点上。为了能利用master的资源,我们可以把这个Taint
清除掉。
kubectl taint node --all node-role.kubernetes.io/master-
其实在本地的集群节点中,为了节约主机内存我是想只保留master节点的,仍然保留worker节点主要是为了保证后面要部署的
rook-ceph
插件有足够的OSD节点数。
安装部署 Rook Ceph 插件
git clone --single-branch --branch release-1.2 https://github.com/rook/rook.git
kubectl create -f rook/cluster/examples/kubernetes/ceph/common.yaml
sed '/ROOK_ENABLE_FLEX_DRIVER/{N;s/false/true/;P;D;}' rook/cluster/examples/kubernetes/ceph/operator.yaml > rook/cluster/examples/kubernetes/ceph/operator.flex_enabled.yaml # 编辑 operator.yaml 设置 ROOK_ENABLE_FLEX_DRIVER 为 true ,否则 pod 无法挂载 volume。
kubectl create -f rook/cluster/examples/kubernetes/ceph/operator.flex_enabled.yaml
kubectl create -f rook/cluster/examples/kubernetes/ceph/cluster-test.yaml
部署 dashboard
安装
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc1/aio/deploy/recommended.yaml
登录 dashboard
创建登录用户,这里创建的是管理员权限用户,生产环境的话要谨慎操作
cat < _token.txt # 取出admin-user的token保存
kubectl config --kubeconfig dashboard-admin.conf set-cluster cluster-name # 空的cluster即可,不需要 ca也不需要server
kubectl config --kubeconfig dashboard-admin.conf set-credentials dashboard-admin --token=`cat _token.txt | tr -d '\n'` # 配置user with token
rm -f _token.txt
kubectl config set-context dashboard-admin@cluster-name --kubeconfig dashboard-admin.conf --user dashboard-admin --cluster cluster-name
kubectl config --kubeconfig dashboard-admin.conf use-context dashboard-admin@cluster-name
登录 dashboard
使用kubectl proxy
命令打开本地代理,之后访问http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
即可打开dashboard页面。在登录页面,使用 kubeconfig方式 + 前面生成的 dashboard-admin.conf 文件进行登录即可。
目前已知问题
- PV可创建,也成功与PVC绑定,但Pod无法挂载Volume。本人不了解
Ceph
存储,可能是配置PV的方式不正确。报错如下:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 47s (x5 over 2m8s) default-scheduler error while running "VolumeBinding" filter plugin for pod "pv-pod": pod has unbound immediate PersistentVolumeClaims
Normal Scheduled 38s default-scheduler Successfully assigned default/pv-pod to k8s-master
Normal SuccessfulAttachVolume 38s attachdetach-controller AttachVolume.Attach succeeded for volume "pv-volume"
Warning FailedMount 4s (x7 over 36s) kubelet, k8s-master MountVolume.WaitForAttach failed for volume "pv-volume" : fail to check rbd image status with: (executable file not found in $PATH), rbd output: ()
不过使用StorageClass的进行PVC自动创建绑定PV可以正常工作,应该是手动配置PV的配置没有写对造成的吧。
参考: