前言
前端时间一直再看Go基础语法,有点头晕目眩,缓一缓,先安装k8s,为k8s学习搭建基础环境。
环境介绍
采用VMware Fusion+centos7虚拟机,Docker作为容器运行环境,版本20.10.24,kubernetes版本为1.21。
| 机器名 | ip | cpu和内存 |
|---|---|---|
| k8s-master | 10.0.0.100 | 2核4g |
| k8s-node01 | 10.0.0.101 | 2核4g |
| k8s-node02 | 10.0.0.102 | 2核4g |
搭建虚拟机的过程就不说了,比较简单,网上很多教程。下面内容都是基于以及搭建好centos7虚拟环境来进行的。
修改主机名称
分别设置三台虚拟机的主机名称:
sudo hostnamectl set-hostname 新的主机名
新的主机名分别是k8s-master、k8s-node01、k8s-node02。
检查是否修改成功,执行如下命令:
hostnamectl status
配置IP
分别给三台机器设置固定ip,执行如下命令:
vim /etc/sysconfig/network-scripts/ifcfg-eth0
修改为自己指定IP即可。
执行下面命令,重启网络生效:
systemctl restart network
配置hosts解析
分别在三台机器上执行如下命令:
cat >> /etc/hosts << EOF
10.0.0.100 k8s-master
10.0.0.101 k8s-node01
10.0.0.102 k8s-node02
EOF
执行如下命令,验证是否可以正常解析:
ping -c 4 k8s-master
ping -c 4 k8s-node01
ping -c 4 k8s-node02
在 ping 命令中, -c 选项用于指定要发送的 ICMP 报文数量,即要发起的 ping 请求次数。在 -c 后面可以跟一个数字,表示发送 ICMP 报文的次数。 所以, ping -c 4 k8s-node01 中的 -c 4 意思是发起对主机 k8s-node01 的 ICMP ping 请求,并且指定发送 4 个 ICMP 报文,即发送 4 次 ping 请求。这样可以让 ping 命令发送多次请求以测试主机的连通性和响应时间。
如果解析正常,会输出如下内容:
PING k8s-node02 (10.0.0.102) 56(84) bytes of data.
64 bytes from k8s-node02 (10.0.0.102): icmp_seq=1 ttl=64 time=1.54 ms
64 bytes from k8s-node02 (10.0.0.102): icmp_seq=2 ttl=64 time=1.50 ms
64 bytes from k8s-node02 (10.0.0.102): icmp_seq=3 ttl=64 time=1.13 ms
64 bytes from k8s-node02 (10.0.0.102): icmp_seq=4 ttl=64 time=1.55 ms
--- k8s-node02 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
当然,还有另外一种验证方式,执行如下命令:
getent hosts k8s-master
getent hosts k8s-node01
getent hosts k8s-node02
解析成功的话会输出如下内容:
10.0.0.100 k8s-master
10.0.0.101 k8s-node01
10.0.0.102 k8s-node02
关闭防火墙
CentOS 7 默认启动了防火墙服务 (firewalld.service),而Kubernetes的Master与工作Node之间会有大量的网络通信。安全的做法是在防火墙上配置各组件需要相互通信的端口号,这里我们先采用简单办法,关闭防火墙,执行如下命令
systemctl stop firewalld && systemctl disable firewalld
关闭SELinux
分别在三台机器上执行如下命令:
vim /etc/sysconfig/selinux
将SELINUX=enforcing修改为 SELINUX=disabled,让容器可以读取主机文件系统。
修改后,查看状态进行验证:
getenforce
关闭系统交换分区
kubeadm需要关闭Linux的swap系统交换区,执行如下命令:
swapoff -a && sed -ri 's/.*swap.*/#&/' /etc/fstab
输入如下命令,验证是否已关闭:
free
安装docker
执行如下命令,下载docker源:
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
执行如下命令,列出docker所有版本:
yum list docker-ce --showduplicates
执行如下命令,安装指定docker版本:
yum install docker-ce-20.10.24 docker-ce-cli-20.10.24 -y
启动docker并设置开机启动:
systemctl enable docker && systemctl start docker
执行如下命令,配置国内源优化下载速度:
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://mw86j9k8.mirror.aliyuncs.com"]
}
EOF
执行如下命令,设置docker驱动为systemd,保持与k8s一致:
vim /etc/docker/daemon.json
增加如下内容:
{
"registry-mirrors": ["https://mw86j9k8.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
最后,执行如下命令重新启动:
systemctl restart docker
可以输入如下命令,验证docker是否安装成功:
docker info
配置yum源
分别在三台机器上,执行如下命令:
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
执行如下命令,清除更新yum缓存:
yum clean all
yum -y makecache
安装kubeadm、kubelet和kubectl
执行如下命令,查看可安装版本;
yum list kubelet --showduplicates | sort -r
执行如下命令安装kubeadm、kubelet和kubectl:
yum install -y kubelet-1.21.0 kubeadm-1.21.0 kubectl-1.21.0
kubeadm将使用kubelet服务以容器方式部署和启动Kubernetes的主要服务,所以需要先启动kubelet服务。运行systemctl start命令启动kubelet 服务,并设置为开机自启动:
systemctl start kubelet && systemctl enable kubelet
输入如下命令,查看版本:
kubelet --version
为了加快kubeadm创建集群的过程,可以预先将所需镜像下载完 成。可以通过如下命令查看镜像列表
kubeadm config images list
执行后,会输出如下内容:
k8s.gcr.io/kube-apiserver:v1.19.16
k8s.gcr.io/kube-controller-manager:v1.19.16
k8s.gcr.io/kube-scheduler:v1.19.16
k8s.gcr.io/kube-proxy:v1.19.16
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.9-1
k8s.gcr.io/coredns:1.7.0
可以看到我们需要下载这些镜像,未下载之前,输入docker images是没有这些镜像的
在 CentOS 上安装 Kubernetes 的过程中,配置 /etc/sysctl.d/k8s.conf 文件并设置以下内核参数是一个重要的步骤。具体来说,这些配置项的作用如下:
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
iptables
三台机器分别执行如下命令:
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
加载配置 :使配置生效,可以通过以下命令立即应用配置:
sysctl --system
验证配置 :确保配置已成功应用,可以通过以下命令检查:
sysctl net.bridge.bridge-nf-call-ip6tables
sysctl net.bridge.bridge-nf-call-iptables
应该看到输出为 1 ,表示配置已生效。
-
net.bridge.bridge-nf-call-ip6tables = 1
- 作用 :这个设置确保了 IPv6 流量通过
iptables进行过滤。当流量经过 Linux 内核的桥接接口时,这个参数指示内核调用ip6tables进行处理。 - 原因 :尽管 Kubernetes 默认使用的是 IPv4,但在某些场景下(如双栈网络或未来可能的 IPv6 支持),需要确保内核能够正确处理 IPv6 流量。
- 作用 :这个设置确保了 IPv6 流量通过
-
net.bridge.bridge-nf-call-iptables = 1
- 作用 :这个设置确保了 IPv4 流量通过
iptables进行过滤。当流量经过 Linux 内核的桥接接口时,这个参数指示内核调用iptables进行处理。 - 原因 :Kubernetes 网络插件(如 Flannel、Calico 等)通常依赖于
iptables规则来管理网络流量和隔离。因此,需要确保桥接流量能够被iptables处理。
- 作用 :这个设置确保了 IPv4 流量通过
为什么需要这些配置
Kubernetes 集群中的网络组件(例如 kube-proxy 和网络插件)大量依赖 iptables 规则来实现服务发现、负载均衡、Pod 网络通信等功能。特别是在使用基于桥接的网络插件时,如果没有这两个配置项,桥接流量将不会被 iptables 处理,从而导致网络策略和安全规则无法生效。这可能会导致一些网络问题,例如:
- Pod 之间的通信问题
- 服务无法访问
- 网络策略不生效 配置这些内核参数是为了确保 Kubernetes 集群中的网络流量能够正确地通过
iptables进行处理,以确保网络策略和安全规则能够正常生效。这是 Kubernetes 安装过程中确保网络正常运行的重要步骤之一。
修改kubeadm的默认配置,国外源变为国内源
执行如下命令,获取默认配置:
kubeadm config print init-defaults > init.default.yaml
然后,复制一份:
cp init.default.yaml init-config.yaml
修改init-config.yaml配置,修改镜像仓库地址,默认拉取镜像地址k8s.gcr.io国内无法访问,这里指定阿里云镜像仓库地址。找到imageRepository,
imageRepository: registry.aliyuncs.com/google_containers
然后,我们执行如下命令下载镜像:
kubeadm config images pull --config=init-config.yaml
等待下载完成,再次输入docker images查看,
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.aliyuncs.com/google_containers/kube-apiserver v1.21.0 4d217480042e 3 years ago 126MB
registry.aliyuncs.com/google_containers/kube-proxy v1.21.0 38ddd85fe90e 3 years ago 122MB
registry.aliyuncs.com/google_containers/kube-scheduler v1.21.0 62ad3129eca8 3 years ago 50.6MB
registry.aliyuncs.com/google_containers/kube-controller-manager v1.21.0 09708983cc37 3 years ago 120MB
registry.aliyuncs.com/google_containers/pause 3.4.1 0f8457a4c2ec 3 years ago 683kB
registry.aliyuncs.com/google_containers/etcd 3.4.13-0 0369cf4303ff 3 years ago 253MB
这一步可能会报如下错误:
failed to pull image "registry.aliyuncs.com/google_containers/coredns/coredns:v1.8.0": output: Error response from daemon: pull access denied for registry.aliyuncs.com/google_containers/coredns/coredns, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
可以输入下面命令进行解决:
docker pull coredns/coredns:1.8.0
docker tag coredns/coredns:1.8.0 registry.aliyuncs.com/google_containers/coredns/coredns:v1.8.0
docker rmi -f coredns/coredns:1.8.0
部署kubernetes Master节点
执行如下命令:
kubeadm init \
--apiserver-advertise-address=10.0.0.100 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.21.0 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=all
执行成功后,注意最后,会生成集群加入命令,如下:
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 10.0.0.100:6443 --token ijffbx.o5kl11dn3iifcaaz \
--discovery-token-ca-cert-hash sha256:b15dae4a130a6510669291eb80bc1fbe4cff22922905f01dced5b303258ce573
apiserver-advertise-address地址必须是master机器的IPkubernetes-version指定k8s版本image-repository指定容器镜像的存储库地址。在该示例中,使用阿里云容器镜像服务。service-cidr指定服务网络的 CIDR 范围。该范围用于分配给 Kubernetes 服务的 IP 地址。pod-network-cidr指定 Pod 网络的 CIDR 范围。该范围用于分配给集群中每个 Pod 的 IP 地址。ignore-preflight-errors=NumCPU,Mem用于初始化 Kubernetes 集群并忽略内存大小限制
没有记住初始化master节点时集群加入命令,也可执行下面命令获取:
kubeadm token create --print-join-command
node节点加入master节点
分别在k8s-node01和k8s-node02机器上执行如下命令,
kubeadm join 10.0.0.100:6443 --token ijffbx.o5kl11dn3iifcaaz \
--discovery-token-ca-cert-hash sha256:b15dae4a130a6510669291eb80bc1fbe4cff22922905f01dced5b303258ce573
执行成功后,在master机器上执行如下命令:
kubectl get nodes
会看到如下输出:
NAME STATUS ROLES AGE VERSION
k8s-node01 NotReady <none> 118m v1.21.0
k8s-node02 NotReady <none> 3h15m v1.21.0
可以看到各节点均为NotReady状态,这是因为没有安装CNI网络插件.
执行如下命令,查看pod状态:
kubectl get pods -n kube-system
不出意外的话,可以看到croedns的状态为Pending。kubeadm初步安装完成的集群不具备网络功能,任何Pod(包括自带的CoreDNS)都无法正常工作
查看集群状态
执行如下命令:
kubectl get cs
正常,应该输出如下内容:
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true"}
或许你会遇到下面的错误:
scheduler Unhealthy Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0.1:10251: connect: connection refused
controller-manager Unhealthy Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0.1:10252: connect: connection refused
解决方案,执行如下命令,分别将文件中的port=0这一行注释掉(使用#来注释):
vim /etc/kubernetes/manifests/kube-controller-manager.yaml
vim /etc/kubernetes/manifests/kube-scheduler.yaml
再次检查状态,就正常了。
安装网络插件
执行如下命令:
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml
这里需要代理,不然镜像大概率下载失败,我连了代理还是下载失败,像下面这样
kubectl get po -A -owide
输出如下内容:
kube-flannel kube-flannel-ds-24sbb 0/1 Init:1/2 0 24s 10.0.0.101 k8s-node01 <none> <none>
kube-flannel kube-flannel-ds-fdw6g 0/1 Init:1/2 0 52m 10.0.0.100 k8s-master <none> <none>
kube-flannel kube-flannel-ds-jlpmj 0/1 Init:ErrImagePull 0 52m 10.0.0.102 k8s-node02 <none> <none>
kube-system coredns-545d6fc579-k8gjk 0/1 Pending 0 114m <none> <none> <none> <none>
kube-system coredns-545d6fc579-lqwr8 0/1 Pending 0 114m <none> <none> <none> <none>
kube-system etcd-k8s-master 1/1 Running 0 114m 10.0.0.100 k8s-master <none> <none>
kube-system kube-apiserver-k8s-master 1/1 Running 0 114m 10.0.0.100 k8s-master <none> <none>
kube-system kube-controller-manager-k8s-master 1/1 Running 0 74m 10.0.0.100 k8s-master <none> <none>
kube-system kube-proxy-ddsbg 1/1 Running 0 114m 10.0.0.100 k8s-master <none> <none>
kube-system kube-proxy-vpn5l 1/1 Running 0 96m 10.0.0.102 k8s-node02 <none> <none>
kube-system kube-proxy-z9w7j 1/1 Running 0 96m 10.0.0.101 k8s-node01 <none> <none>
kube-system kube-scheduler-k8s-master 1/1 Running 0 73m 10.0.0.100 k8s-master <none> <none>
通过下面命令,看看pod的详细信息:
kubectl describe po -n kube-flannel kube-flannel-ds-24sbb
通过输出内容,可以看到需要下面2个镜像:
docker.io/flannel/flannel-cni-plugin:v1.4.1-flannel1
docker.io/flannel/flannel:v0.25.4
当然你也可以通过kube-flannel.yml来查看,搜索image
我是怎么解决的呢,在hub.docker.com/官网下载这两个镜像,虚…
rz
上传完成后,执行如下命令:
docker load -i flannel.tar.gz
docker load -i flannel-0254.tar.gz
然后删除原来pod,执行如下命令:
kubectl delete po -n kube-flannel kube-flannel-ds-24sbb kube-flannel-ds-fdw6g kube-flannel-ds-jlpmj
再次执行下面命令,查看状态;
kubectl get po -A -owide
可以看到输出正常了:
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-flannel kube-flannel-ds-299f9 1/1 Running 0 35s 10.0.0.100 k8s-master <none> <none>
kube-flannel kube-flannel-ds-2f9zq 1/1 Running 0 5s 10.0.0.102 k8s-node02 <none> <none>
kube-flannel kube-flannel-ds-z24qf 1/1 Running 0 34s 10.0.0.101 k8s-node01 <none> <none>
kube-system coredns-545d6fc579-k8gjk 1/1 Running 0 125m 10.244.2.3 k8s-node02 <none> <none>
kube-system coredns-545d6fc579-lqwr8 1/1 Running 0 125m 10.244.2.2 k8s-node02 <none> <none>
kube-system etcd-k8s-master 1/1 Running 0 125m 10.0.0.100 k8s-master <none> <none>
kube-system kube-apiserver-k8s-master 1/1 Running 0 125m 10.0.0.100 k8s-master <none> <none>
kube-system kube-controller-manager-k8s-master 1/1 Running 0 85m 10.0.0.100 k8s-master <none> <none>
kube-system kube-proxy-ddsbg 1/1 Running 0 125m 10.0.0.100 k8s-master <none> <none>
kube-system kube-proxy-vpn5l 1/1 Running 0 107m 10.0.0.102 k8s-node02 <none> <none>
kube-system kube-proxy-z9w7j 1/1 Running 0 107m 10.0.0.101 k8s-node01 <none> <none>
kube-system kube-scheduler-k8s-master 1/1 Running 0 84m 10.0.0.100 k8s-master <none> <none>
kubectl命令补全
执行如下命令:
echo "source <(kubectl completion bash)" >> ~/.bash_profile
source .bash_profile
常见报错
执行kubectl get nodes,报错The connection to the server 10.0.0.100:6443 was refused - did you specify the right host or port?
出现这个问题的原因是kubectl命令需要使用kubernetes-admin来运行
在master节点上执行如下命令,将master节点中的/etc/kubernetes/admin.conf文件拷贝到从节点相同目录下:
scp -rp /etc/kubernetes/admin.conf root@10.0.0.101:/etc/kubernetes/
scp -rp /etc/kubernetes/admin.conf root@10.0.0.102:/etc/kubernetes/
在msater和node节点上分别执行如下命令:
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
执行如下命令,立即生效:
source ~/.bash_profile
最后
经过努力,我终于完成了环境搭建工作。虽然耗费了我整整一天的时间,但在这个过程中遇到了许多问题并上网查找资料,还请教过运维的同事。值得庆幸的是,今天我成功地搭建起了这个k8s环境。接下来,我将投入更多精力进行深入研究和学习。