kubeadm 部署
centos安装k8s
设置k8s的yum仓库地址,然后使用yum命令进行安装
cat <<EOF > /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
EOF
setenforce 0
yum install -y kubelet kubeadm kubectl
systemctl enable -now kubelet
kubeadm:用来初始化集群的命令行工具。
kubelet:在集群中的每个节点上用来启动 pod 和容器等的后台进程。
kubectl:用来与集群通信的命令行工具。
安装完成后启动kubelet。
k8s集群运行先决条件
1, cpu数量大于等于2, 否则会报以下错误
[ERROR NumCPU]: the number of available CPUs 1 is less than the required 2
2, docker服务必须首先运行
systemctl start docker.service
3, 必须关闭swap, 否则报以下错误
[ERROR Swap]: running with swap on is not supported. Please disable swap
关闭swap方法,在 /etc/fstab 中,将含有swap的一行开头以#注释, 然后重启系统即可。 可以使用top命令来查看,swap 内存为零。
通过命令直接关闭swap : swapoff -a
4, 设置bridge调用iptables, 否则会出现以下错误:
[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1
设置方法,在/etc/sysctl.conf 增加以下一行:
net.bridge.bridge-nf-call-iptables = 1
5, etcd提示目录非空, 错误输出如下
[ERROR DirAvailable--var-lib-etcd]: /var/lib/etcd is not empty
解决方法: rm /var/lib/etcd/* -rf
6, 关闭selinux
在 /etc/sysconfig/selinux 中将SELINUX值改为disabled, 然后重启系统
关闭selinux的原因是允许容器访问宿主机的文件系统, 重启后运行 sestatus 命令查看是否生效。
[zhang@zhang1 ~]$ sestatus
SELinux status: disabled
kubeadm
kubeadm是k8s集群的一个配置工具。
初始化集群
kubeadm init 命令启动一个 Kubernetes 主节点(管理节点)
kubeadm init --apiserver-advertise-address=192.168.101.180 --image-repository registry.aliyuncs.com/google_containers --service-cidr=10.1.0.0/16 --pod-network-cidr=10.244.0.0/16 --v=5
这是控制面初始化,执行时,需要从网络上下载镜像,因此需要一定的时间。192.168.101.180为服务器的IP, 需要更换为自己服务器的地址。启动成功后会输出以下类似信息
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 192.168.56.128:6443 --token 983c4t.obppxddoze3n4tsf \
--discovery-token-ca-cert-hash sha256:186259c430f7d89d96ba63691ba625149c80abfbd510cfcd351f4330b1c43146
kubeadm join 192.168.56.128:6443 --token e6rnfa.d0igvvnsd8o25isa \
--discovery-token-ca-cert-hash sha256:5cd1d0b61cc18dca9964e0c2827a9f72ef30ffca54bf8acaf5ce03c38cb66055
最后两行的输出包含密码等私有信息,不能泄漏,否则有可能导致恶意攻击及信息被盗等风险。
各选项含义如下:
“–apiserver-advertise-address”, api服务器地址。使用与默认网关关联的网络接口来设置此控制平面节点 API server 的广播地址。如果服务器有多个IP, 使用该选项来修改api服务器地址。
–image-repository registry.aliyuncs.com/google_containers
–service-cidr=10.1.0.0/16
–pod-network-cidr=10.244.0.0/16
-control-plane-endpoint 可用于为所有控制平面节点设置共享端点。 允许 IP 地址和可以映射到 IP 地址的 DNS 名称。
可以使用以下命令来查看其默认参数
kubeadm config print init-defaults
拉取镜像命令
kubeadm config images pull
如果计划将单个控制平面 kubeadm 集群升级成高可用, 应该指定 –control-plane-endpoint 为所有控制平面节点设置共享端点。 端点可以是负载均衡器的 DNS 名称或 IP 地址。
管理节点创建完成后可以获取令牌
kubeadm token list
如果管理节点创建不正确,可以通过以下命令进行删除,这将对控制平面进行清理。 运行这个命令一定要慎重。
$ kubeadm reset
通过 netstat 来查看提供的tcp服务。
[root@zhang1 ~]# netstat -ltnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 2724/kubelet
tcp 0 0 127.0.0.1:10249 0.0.0.0:* LISTEN 2855/kube-proxy
tcp 0 0 192.168.56.128:2379 0.0.0.0:* LISTEN 2575/etcd
tcp 0 0 127.0.0.1:2379 0.0.0.0:* LISTEN 2575/etcd
tcp 0 0 192.168.56.128:2380 0.0.0.0:* LISTEN 2575/etcd
tcp 0 0 127.0.0.1:2381 0.0.0.0:* LISTEN 2575/etcd
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 851/rpcbind
tcp 0 0 127.0.0.1:10257 0.0.0.0:* LISTEN 2559/kube-controlle
tcp 0 0 127.0.0.1:10259 0.0.0.0:* LISTEN 2481/kube-scheduler
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1129/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1498/master
tcp 0 0 127.0.0.1:39778 0.0.0.0:* LISTEN 2724/kubelet
tcp6 0 0 :::10250 :::* LISTEN 2724/kubelet
tcp6 0 0 :::6443 :::* LISTEN 2513/kube-apiserver
tcp6 0 0 :::111 :::* LISTEN 851/rpcbind
tcp6 0 0 :::10256 :::* LISTEN 2855/kube-proxy
tcp6 0 0 :::22 :::* LISTEN 1129/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1498/master
10248, 检查健康服务的端口。
10250,kubelet 服务监听的端口,它接收并执行 Master 发来的指令。
6443, kube apiserver监听端口。
节点已经为Ready状态
[zhang@zhang1 ~]$ kubectl get node
NAME STATUS ROLES AGE VERSION
zhang1 Ready master 3d17h v1.19.4
获取所有的pod, 以下是各组件均运行正常的输出,STATUS字段均为”Running”
[root@zhang1 zhang]# kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-6d56c8448f-55r84 1/1 Running 1 2d17h
kube-system coredns-6d56c8448f-7smch 1/1 Running 1 2d17h
kube-system etcd-zhang1 1/1 Running 37 2d17h
kube-system kube-apiserver-zhang1 1/1 Running 35 2d17h
kube-system kube-controller-manager-zhang1 1/1 Running 5 2d17h
kube-system kube-flannel-ds-zlvkl 1/1 Running 1 2d16h
kube-system kube-proxy-d8ndl 1/1 Running 1 2d17h
kube-system kube-scheduler-zhang1 1/1 Running 5 2d17h
查看kubernetes默认的名字空间的节点
kubectl get pods -n kube-system
工作节点
工作节点加入到集群中, 需要服务器地址和token, token可以在服务器上生成,命令为
kubeadm token create
加入集群
kubeadm join 192.168.101.172:6443 --token rgpuv4.3f5otdr81civra5o \
--discovery-token-ca-cert-hash sha256:5cd1d0b61cc18dca9964e0c2827a9f72ef30ffca54bf8acaf5ce03c38cb66055
或
kubeadm join 192.168.101.172:6443 --token rgpuv4.3f5otdr81civra5o --discovery-token-unsafe-skip-ca-verification
节点加入后,可以拷贝其授权,便于后续查看配置:
cp -i /etc/kubernetes/kubelet.conf $HOME/.kube/config
如果该节点不使用,可以删除节点
kubectl delete node <node_name>
问题及分析
问题, pods的状态始终为“Init:CrashLoopBackOff”
解决方法: 可能时未关闭swap导致。 关闭swap。 也可能是容器网络镜像未下载成功,使用docker命令进行下载
docker pull quay.io/coreos/flannel:v0.13.0-rc2
出现以下错误 8080 was refused 访问错误
[zhang@localhost ~]$ kubectl get nodes
The connection to the server localhost:8080 was refused - did you specify the right host or port?
解决方法: 切换到普通用户,然后执行
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
节点状态为 NotReady, 如何定位解决
[root@zhang1 ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION zhang1 NotReady master 10m v1.19.2
解决方法: 通过部署flannel即可解决, 部署命令:
kubectl apply -f kube-flannel.yml
还有一种可能是防火墙的问题,则关闭防火墙看看问题是否解决
systemctl stop firewalld
如果出现问题,可以查看log输出来分析问题,log日志文件为 /var/log/messages
[root@zhang1 zhang]# tail /var/log/messages -f
Sep 24 22:31:53 zhang1 journal: I0925 02:31:53.588956 1 client.go:360] parsed scheme: "passthrough"
Sep 24 22:31:53 zhang1 journal: I0925 02:31:53.589027 1 passthrough.go:48] ccResolverWrapper: sending update to cc: {[{https://127.0.0.1:2379 <nil> 0 <nil>}] <nil> <nil>}
Sep 24 22:31:53 zhang1 journal: I0925 02:31:53.589041 1 clientconn.go:948] ClientConn switching balancer to "pick_first"
Sep 24 22:31:58 zhang1 journal: 2020-09-25 02:31:58.836057 I | etcdserver/api/etcdhttp: /health OK (status code 200)
Sep 24 22:32:08 zhang1 journal: 2020-09-25 02:32:08.837435 I | etcdserver/api/etcdhttp: /health OK (status code 200)
Sep 24 22:32:18 zhang1 journal: 2020-09-25 02:32:18.839329 I | etcdserver/api/etcdhttp: /health OK (status code 200)
Sep 24 22:32:28 zhang1 journal: 2020-09-25 02:32:28.836484 I | etcdserver/api/etcdhttp: /health OK (status code 200)
Sep 24 22:32:29 zhang1 journal: I0925 02:32:29.550966 1 client.go:360] parsed scheme: "passthrough"
Sep 24 22:32:29 zhang1 journal: I0925 02:32:29.551020 1 passthrough.go:48] ccResolverWrapper: sending update to cc: {[{https://127.0.0.1:2379 <nil> 0 <nil>}] <nil> <nil>}
Sep 24 22:32:29 zhang1 journal: I0925 02:32:29.551033 1 clientconn.go:948] ClientConn switching balancer to "pick_first"
Sep 24 22:32:38 zhang1 journal: 2020-09-25 02:32:38.836072 I | etcdserver/api/etcdhttp: /health OK (status code 200)
如果还不能解决,则通过 journalctl -f -u kubelet 命令查看输出,然后根据输出分析定位问题。
我这里出现启动两个etcd导致 kube-apiserver 进程运行异常的问题。首次运行正常,在重启了主机之后 发现kube-apiserver连接不上,原来是主机和虚拟机都启动了etcd,导致配置信息读取异常。
解决方法,将主机的etcd进程关闭,命令为
systemctl disable etcd
systemctl stop etcd
进入运行中的容器:
kubectl exec buildbot-zhang2-5413be -it /bin/bash
proxy
指定地址–address, 指定端口–port
kubectl proxy –address=0.0.0.0 –port=8009
debug
安装netstat, 这样可以查看k8s绑定的端口
yum -y install net-tools
sudo mkdir /etc/cni/net.d -p systemctl restart docker
设置工作节点角色
如果没有设置,节点的ROLES状态为<none> 设置前
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready <none> 14d v1.19.2
node2 Ready <none> 14d v1.19.2
zhang1 Ready master 14d v1.19.2
设置节点的角色命令为label, 原理就是给 node 打标签, 只不过是特殊的标签
kubectl label node node1 node-role.kubernetes.io/worker=worker
设置完成后,工作节点的角色从<none>变为 worker
kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready worker 14d v1.19.2
node2 Ready worker 14d v1.19.2
zhang1 Ready master 14d v1.19.2
重新部署
如果遇到某种原因需要重新部署k8s集群,例如服务器IP地址发生了改变。
1, 先关闭kubelet
systemctl stop kubelet
2, 停止docker容器和删除docker镜像
docker stop $(docker ps -q)
docker rm $(docker ps -a -q)
3, 删除etcd 的配置
rm /etc/kubernetes -rf
rm /var/lib/etcd/ -rf
4, 执行 kubeadm reset
5, 初始化管理节点
kubeadm init --apiserver-advertise-address=192.168.101.180 --image-repository registry.aliyuncs.com/google_containers --service-cidr=10.1.0.0/16 --pod-network-cidr=10.244.0.0/16
our 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 192.168.101.180:6443 --token n0ffnu.kgll39ow235x3ort \
--discovery-token-ca-cert-hash sha256:7067bdcb4bf4694fa7cc590fd01d466ed152860ac69aaa0e145711f60f04bfd4
FAQ
1, 后期想加入新的node, 如何加入。
答: 默认 token 的有效期为 24 小时。当过期之后,该 token 就不可用了, 我们可以重新生成新的token, 然后使用token list 命令来查看,如下
kubeadm token create
kubeadm token list
加入方法
kubeadm join --token qrepul.kvk46vhw4vdd4lut 192.168.101.172:6443 --discovery-token-unsafe-skip-ca-verification
2, Failed to create pod sandbox
pod创建状态始终为”Init:0/1”, 使用kubectl describe命令查看pod提示以下错误
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedCreatePodSandBox 4m5s (x740 over 164m) kubelet, bj-zhang1 Failed to create pod sandbox: open c: no such file or directory
解决方法: 我这里在centOs7遇到该错误,因为没有安装系统dns组件,安装 systemd-resolved后解决,安装命令
yum install -y systemd-resolved
systemctl enable --now systemd-resolved
等待几分钟,程序会自动去创建POD
参考资料
Kubernetes 官方文档 https://kubernetes.io/zh/docs/home/