摘要:最近有个需求,需要搭建一个k8s集群,但是集群不要太大,所以就选择了轻量级的kubeadm来搭建这个集群,然后顺便就记录了下来,下面我就跟大家分享下,集群的搭建和,踩过的坑。然后呢,请大家注意下我最后面的一个栏目(第八点),这里可能有你要的答案。
基础环境
用途 | 操作系统 | IP | 安装组件 |
---|---|---|---|
master | centos7.6 | 10.10.75.44 | kubeadm v1.15.3,kubectl v1.15.3,kubelet v1.15.3,docker 18.06.3-ce |
node1 | centos7.6 | 10.10.75.45 | kubeadm v1.15.3,kubelet v1.15.3,docker 18.06.3-ce |
node2 | centos7.6 | 10.10.75.46 | kubeadm v1.15.3,kubelet v1.15.3,docker 18.06.3-ce |
node3 | centos7.6 | 10.10.75.47 | kubeadm v1.15.3,kubelet v1.15.3,docker 18.06.3-ce |
服务名称 | 作用 |
---|---|
kubeadm | 用来初始化集群指令 |
kubelet | 在集群中的每个节点上都需要安装,用来启动pod等 |
kubectl | 用来与集群通信的命令行工具 |
一.安装Docker(master和node都需要安装)
1.卸载原有docker
systemctl stop docker
yum remove -y docker docker-common docker-selinux docker-engine
rm -fr /var/lib/docker
2.关闭selinux ,关闭swap分区
(1)
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
(2)
swapoff -a
然后vim /etc/fstab 注释掉swap分区
3.配置docker的yum文件
/usr/bin/yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
/usr/bin/yum clean all;/usr/bin/yum makecache
/usr/bin/yum update -y
/usr/bin/yum install -y yum-utils device-mapper-persistent-data lvm2
4.安装docker(这里是安装最新的,你可以根据实际需要来安装)
/usr/bin/yum install -y \
`/usr/bin/yum list docker-ce --showduplicates | sort -r |grep docker | head -1 | awk -F '.x' '{print $1,$2 }'| awk '{print$1 "-" $3}'`
systemctl restart docker
systemctl enable docker
注意:如果你想用原生的overlay2的文件系统,则到此就可以start docker 就可以用了,但是如果你用的老的版本,或者想使用其他文件系统,则可以看下后面的配置,比如我们使用device-mapper则还需要做以下配置
5.创建direct-lvm(可选,我这里用的是device-mapper)
注意:这里是我们专门申请了一块盘,用来做lvm,这块盘只需要分区,不需要挂载
data_dev="/dev/sdb1"
pvcreate -y ${data_dev}
vgcreate docker ${data_dev}
lvcreate --wipesignatures y -n thinpool docker -l 95%VG
lvcreate --wipesignatures y -n thinpoolmeta docker -l 1%VG
lvconvert -y --zero n -c 512K --thinpool docker/thinpool --poolmetadata docker/thinpoolmeta
cat > /etc/lvm/profile/docker-thinpool.profile << EOF
activation {
thin_pool_autoextend_threshold=80
thin_pool_autoextend_percent=20
}
EOF
lvchange --metadataprofile docker-thinpool docker/thinpool
lvs -o+seg_monitor
6.配置和启动docker(可选,我这里用的是device-mapper)
#配置docker
mkdir /etc/docker
cat > /etc/docker/daemon.json << EOF
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "5"
},
"default-ulimit": ["nofile=102400:102400"],
"ipv6": false,
"debug": true,
"log-level": "debug",
"storage-driver": "devicemapper",
"storage-opts": [
"dm.thinpooldev=/dev/mapper/docker-thinpool",
"dm.use_deferred_removal=true",
"dm.use_deferred_deletion=true"
],
"selinux-enabled": false,
"registry-mirrors": ["registry.xxxx"] #这里如果你有自己搭建镜像仓库可以写你自己的,如果没有可以把这一行注释掉,不然docker起不来
}
EOF
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
sysctl -p
systemctl restart docker
systemctl enable docker
至此,我们的docker安装完毕了,下面我们在来安装其他组件
二.安装kubeadm,kubelet(master和node上都需要安装)
1.配置yum源
vim /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
1.安装kubelet,kubeadm
yum install -y kubelet kubeadm
三.kubeadm创建集群(master上运行)
1.创建集群
kubeadm init --kubernetes-version=v1.15.3 --apiserver-advertise-address 10.10.75.44 --pod-network-cidr=172.30.0.0/16
--kubernets-versio: 意思是指定k8s版本
--apiserver-advertise-address:用于指定master的哪个network interface进行通信,如果不指定,则kubeadm会自动选择默认的网关的interface,意思就是说,如果你的服务器只有一个ip,那么就可以不指定,如果有两个ip那么你就指定一下比较明确了,我这里是指定的
--pod-network-cidr: 用于指定pod的网络范围如果没有指定系统默认为(172.244.0.0/16我记得是这样的,如果错了抱歉哈)。
注意:其实我们也可以指定svc的ip段的,如果没有指定系统默认为10.96.0.0/16
在mster上运行成功后保存下面一段用于后面node加入集群,如果node需要加入集群,运行下面命令:
kubeadm join 10.10.75.44:6443 --token pcksl8.9zn081ghtucd81fo --discovery-token-ca-cert-hash sha256:6c6c20ea07cabe926da1c483f12b4934fc5d5b5c2c6547eef5543b188cb8059f #这token是在生成集群的时候留下的
注意:在显示类似上面的10.10.75.44:6443 的同时 则证明集群应该是创建好了所以我们要进行验证
2.安装kubectl(可以在任意服务器安装,我今天是安装在master节点上)
yum install -y kubectl
mkdir -p $HOSE/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
3.验证集群
[root@st01010vm44 hub]# kubectl get node
NAME STATUS ROLES AGE VERSION
st01010vm44 Ready master 141m v1.15.3
[root@st01010vm44 hub]# kubectl get pod --all-namespaces
四.创建网络
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
vm.swappiness=0
EOF
sysctl --system
执行:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml
成功后看到pod启动则没问题:
[root@st01010vm44 hub]# kubectl get pod --all-namespaces |grep flan
kube-system kube-flannel-ds-amd64-4h9x8 1/1 Running 0 50m
kube-system kube-flannel-ds-amd64-6clzl 1/1 Running 2 55m
kube-system kube-flannel-ds-amd64-l5m4w 1/1 Running 1 142m
kube-system kube-flannel-ds-amd64-rn6zq 1/1 Running 2 47m
五.配置集群
1.k8s集群默认是不会将pod建立在master上的,但是我们既然用了kubeam,则证明我们要最大化的利用资源,所以我们可以通过设置使得master服务器也可以被调度,可以被使用命令如下:
kubectl taint nodes --all node-role.kubernetes.io/master-
2.添加其他节点加入集群(node)
记得我上面说过的要保留一段输出文字吗?所以这里就用到了
在一个装有docker,kubeadm,kubelet的服务器上运行:
kubeadm join 10.10.75.44:6443 --token pcksl8.9zn081ghtucd81fo --discovery-token-ca-cert-hash sha256:6c6c20ea07cabe926da1c483f12b4934fc5d5b5c2c6547eef5543b188cb8059f
注意:mster上的6443端口一定要给这些node服务器开放,不然则不通
3.验证集群是否正常(master上运行)
[root@st01010vm44 hub]# kubectl get node
NAME STATUS ROLES AGE VERSION
st01010vm44 Ready master 149m v1.15.3
st01010vm45 Ready <none> 59m v1.15.3
st01010vm46 Ready <none> 54m v1.15.3
st01010vm47 Ready <none> 52m v1.15.3
六.删除集群
1.先删掉节点(在主节点执行)
kubectl drain <node name> --delete-local-data --force --ignore-daemonsets
kubectl delete node <node name>
1.清理从节点
kubeadm reset
rm -rf /etc/kubernetes/
七.安装dashboard(可选)
docker pull k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
到现在为止,我们的集群看样子是安装完成了。但是在用的时候,或者说在安装的时候还需要注意以下几点,这个是我踩过的坑,所以跟大家同步下。
八.采坑,与总结(重要)
1.先运行kubeadm再启动kubelet(甚至不用你手动,kubeadm会自动拉起kubele)
当我们安装好kubelet和kubeadm的时候先不要去运行(systemctl start kubelet)这条命令来打开kubelet,因为如果你运行了就会发现其实kubelet是不能被起来的。所以我们需要先运行kubeadm,这样kubelet才会被自动拉起(我第一次装的时候就卡这里了 )
2.kubelet不能起来的第二个原因(swap没关闭)
如果master服务器重启,或者你的node机器重启,然后你有可能会发现master是notready状态或者node为notready状态,这时候我们排查发现是kubelet没有起来,那么有可能是swap没有关闭,如果swap 没有关闭则kubelet不能起来
3.pod之间不能相互通信
当我们整个集群搭建完毕后,启动了几个pod,但是发现pod是不能ping通或者进行端口访问的(这里的pod指的是pod ip断分配的ip,并不是host模式的pod ip),而且路由也是没问题的,那么这个时候应该是iptables的原因,默认iptable是拒绝转发数据包的,所以我们需要在node节点上执行:
iptables -P FORWARD ACCEPT
iptables -F
这个时候再去看,就会发现pod之间已经可以ping通
4.pod不能访问apiserver(重要,我在看github的时候有好多人问这个问题)
(1) 首先我们从node检查下是不是可以通apiserver,发现是没问题的:
[root@st01010vm44 ~]# curl -kv https://10.10.75.44:6443/version
* About to connect() to 10.10.75.44 port 6443 (#0)
* Trying 10.10.75.44...
* Connected to 10.10.75.44 (10.10.75.44) port 6443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* NSS: client certificate not found (nickname not specified)
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: CN=kube-apiserver
* start date: Sep 11 05:00:17 2019 GMT
* expire date: Sep 10 05:00:17 2020 GMT
* common name: kube-apiserver
* issuer: CN=kubernetes
> GET /version HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 10.10.75.44:6443
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Fri, 27 Sep 2019 02:52:46 GMT
< Content-Length: 263
<
{
"major": "1",
"minor": "15",
"gitVersion": "v1.15.3",
"gitCommit": "2d3c76f9091b6bec110a5e63777c332469e0cba2",
"gitTreeState": "clean",
"buildDate": "2019-08-19T11:05:50Z",
"goVersion": "go1.12.9",
"compiler": "gc",
"platform": "linux/amd64"
* Connection #0 to host 10.10.75.44 left intact
通过上面我们发现apiserver是正常工作的,所以定位问题到pod,然后启动一个busybox去测试功能,顺便我也把busybox的yaml也贴一下:
[root@st01010vm44 hub]# cat centos.yaml
apiVersion: v1
kind: Pod
metadata:
name: centos-t
namespace: kube-system
spec:
containers:
- image: centos
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: centos-t
restartPolicy: Always
然后发现,我们的测试pod是不能通公网的,所以这时候我们想到了flannel,查看配置发现flannel里面的配置的network和我们k8s 里面设置的pod ip段不一样(按道理是必须一样),所以我们需要重新设置flannel.yaml里面的参数和我们设置的pod ip段保存一致,然后生效,命令为:
kubectl apply -f flannel.yaml
有些人可能不明白这个yaml文件在哪。往上翻,我们配置flannel的时候有
**(2)还有就是发现我们pod里面的dns配置既不是我们node的配置,也不是我们集群里面kube-dns的ip(10.96.0.2),而是一个莫名其妙的10.96.0.10(这就是我抄网上文档留下的坑),如下: **
我们知道,pod是通过kubelet来控制的,所以他的cluster dns ip也是在kubelet的配置文件里面定义的,所以我们需要去查看一下kubelet的配置,命令如下:
cat /var/lib/kubelet/config.yaml
然后发现这里的dns配置就是这个10.96.0.10,我们只需要把它改成我们的kube-dns ip(10.96.0.2)就行。
然后重启所有node的kubelet,然后再把pod重建。这样我们就会发现新起来的pod已经可以通外网了,也可以访问apiserver了,感觉一切都好了。没错,我们的集群现在是没问题了,大功告成。
注意:我们搭建集群的时候都几乎是借鉴网上的文档,但是在我们的实际应用中却会发现比较多的问题,而且这些问题google里面总不是你想要的答案,那么我们就需要静下心来,根据系统给的报错提示来一个个解决,然后再根据测试结果和k8s原理来处理一个个问题,这样不仅可以完善集群,也可以增长经验,好了这个文档断断续续写了两天,哈哈,总算写完了,最后欢迎大家来交流–|--|