k8s 部署
kubernetes(k8s)的部署有手动部署和 kubeadm 部署的方式. 还有一些简单的部署方式, 但生产使用主要是使用 kubeadm方式.
以下就介绍 kubeadm 方式部署.
[toc]
处理基础
修改 hostname
# 名称可以根据情况看着设置
hostnamectl set-hostname k8s-master
# hostnamectl set-hostname k8s-node-01
# hostnamectl set-hostname k8s-node-02
固定 IP 地址
K8S 的服务器不能使用 dhcp 的类型.
vim /etc/sysconfig/network-scripts/ifcfg-{网卡号}
# 其他的参数基本不变
BOOTPROTO=static
ONBOOT="yes"
IPADDR="192.168.100.10"
PREFIX="24"
GATEWAY="192.168.100.1"
修改 resolv
如果有需要就修改
# 中国电信, 这个通用. 可以替换成自己本地的.
echo 'nameserver 114.114.114.114' > /etc/resolv.conf
安装基础工具包
# 安装 wget web 请求工具
yum install -y wget
mkdir /etc/yum.repos.d/bak && mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak
# 更新 centos 源
wget -O /etc/yum.repos.d/centos7_base.repo http://mirrors.cloud.tencent.com/repo/centos7_base.repo
wget -O /etc/yum.repos.d/epel-7.repo http://mirrors.cloud.tencent.com/repo/epel-7.repo
# 刷新缓存
yum clean all && yum makecache
# 安装 vim telnet 及网络工具包.
# 安装 yum 扩展管理工具
yum install -y vim curl telnet net-tools yum-utils device-mapper-persistent-data lvm2
修改 hosts
修改 hosts 原因系为了加速对 github 的访问速度和访问失败问题
vim /etc/hosts
# 如果 IP 发生变化, 可以重新定位其真实 IP, 不然下面有些 curl 或 get 或者 kubectl apply 可能会失败
199.232.68.133 raw.githubusercontent.com
199.232.68.133 user-images.githubusercontent.com
199.232.68.133 avatars2.githubusercontent.com
199.232.68.133 avatars1.githubusercontent.com
140.82.114.4 github.com
199.232.69.194 github.global.ssl.fastly.net
140.82.113.9 codeload.github.com
关闭 Linux 功能
# 停止防火墙
systemctl stop firewalld
# 禁止防火墙自动启动
systemctl disable firewalld
# 关闭SELinux(临时)
setenforce 0
# 永久关闭SELinux
sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
# 关闭 Linux swap Area(系统交换区)
swapoff -a # -a 将/etc/fstab文件中所有设置为swap的设备关闭
# 永久关闭 swap area
sed -i 's/.*swap.*/#&/' /etc/fstab
配置网卡转发
设置 ipv4 多网卡数据包转发
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p
配置系统内核
桥接 IPv4流量传递到 iptables 链
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
vm.swappiness=0
EOF
sysctl --system
sysctl -p
设置 bridge-nf-call-iptables 为 1
cat /proc/sys/net/bridge/bridge-nf-call-iptables
# 如果是 0 则修改为 1
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
modprobe br_netfilter
echo "modprobe br_netfilter" >> /etc/rc.local
cat <<EOF> /etc/sysconfig/modules/br_netfilter.modules
modprobe br_netfilter
EOF
chmod 755 /etc/sysconfig/modules/br_netfilter.modules
安装 docker
CRI 使用 docker. 其他的方式介绍请自行搜索, 但因为只要使用了 CRI 或 OCI 标准的容器, 都可以与 K8s 兼容, 即只改变当前<安装 docker>步骤, 其他不需要变动.
RUNTIME
这里的 RUNTIME 主要是概念性的东西, 指的是容器运行时要执行的东西, 其开源标准为 CRI, 即<容器运行时接口>. 更多有关这方面的介绍可以见<TODO待补充>
支持该标准的主要虚拟化系统有:
- docker
- cri-o
- cri-contranerd
- rkt
- frakti
配置 docker daemon
创建 daemon docker 配置 使用
如果有私库, 要加上自己的私库地址.
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://26ujpd31.mirror.aliyuncs.com"],
"exec-opts":["native.cgroupdriver=systemd"],
"iptables":false
}
EOF
私库添加配置[可选配置]
"insecure-registries":["repo.panda-inner.co"],
安装 docker
更新 docker 安装源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
查看可以安装的版本
yum list docker-ce --showduplicates | sort -r
安装 docker, 建议使用最新版本, 同时要考虑与 k8s 的兼容度.
# 为了与其他节点兼容, 当前使用 18.06.3 版本
yum install -y docker-ce-19.03.13-3.el7
# 开启 docker
systemctl enable docker && systemctl start docker && systemctl status docker
安装 k8s
k8s 的编译及处理是非常麻烦的事情, 平常使用建议直接使用二进制安装.
这种方式简单快捷省时省力.
更新 K8s 源
注意, k8s 是 google 开源的服务, 因为一些问题, 我们是不能直接使用原 google 的源的. 不解释.
使用阿里源, 国内访问速度还是很快的.
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
安装 k8s
安装 k8s, 以下操作2选1
安装最新版本(建议)
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet && systemctl start kubelet && systemctl status kubelet
安装指定版本
这里以 1.12.1 举例
yum -y install kubectl-1.12.1-0
yum -y install kubelet-1.12.1-0
yum -y install kubeadm-1.12.1-0
systemctl enable kubelet && systemctl start kubelet && systemctl status kubelet
部署 k8s
以下的安装 master 和 node 将要分开安装, 上面的命令都是完全相同的.
部署 k8s 直接使用 kubeadm 工具, 这个是官方的 Kubernetes 的自动化部署工作.
部署 k8s 分为 Master 和 Node, Master 的部署工具较为复杂和麻烦. 在本教程中 Node 只要加入 master 基本可以自动处理.
使用 kubeadm 创建集群
参数使用 option=args 方式 或 option args 方式
几个参数说明:
--kubernetes-version={version} # 集群 k8s 版本
--apiserver-advertise-address={Master-IP} # apiserver 服务器的 IP 地址, 一般使用 master 做该作用.
--image-repository={仓库URL} # 由于google无法访问的原因, 这里使用阿里云的. 如果有自己的仓库, 直接使用即可, 但一定要包含对应版本的基础组件镜像, 不然无法完成集群安装.
--service-cidr={CIDR} # 设置service的CIDRs,默认为 10.96.0.0/12
--pod-network-cidr={CIDR} # 指定 pod 网络的 IP 地址范围. 如果设置时, k8s 控制中心将自动为每个节点分配 CIDR. 详细介绍请见 pod-network-cidr
--dry-run # 该命令只会将 kubeadm 做的事情输出到标准输出中, 但不会实际执行任何命令, 对于了解 kubeadm 都做了什么, 如何运行是非常重要的.
kubeadm init --kubernetes-version=1.19.3 \
--apiserver-advertise-address=192.168.135.12 \
--image-repository registry.aliyuncs.com/google_containers \
--service-cidr=10.1.0.0/16 \
--pod-network-cidr=10.244.0.0/16
本次执行需要消耗比较多的时间, 需要从网络中下载镜像及安装相关组件.
当安装完成后会给出反馈出一条命令, 这条命令在后续的使用中比较重要.
kubeadm join 192.168.100.10:6443 --token ukdlzf.7l82o3p4qelchdxx
--discovery-token-ca-cert-hash sha256:39def206e699bf9211619a1cfbb1d9c2fabf6c438d6481f6c2fac3983c384fe0
安装 kubectl 工具
kubeadm 安装完成后, kubectl 就已经配置好了, 只需要拿来配置即可直接使用
mkdir -p /root/.kube
cp /etc/kubernetes/admin.conf /root/.kube/config
# 测试
kubectl get nodes
kubectl get cs
部署 Flannel 网络
CNI 容器网络接口
CNI意为容器网络接口,它是一种标准的设计,为了让用户在容器创建或销毁时都能够更容易地配置容器网络。
CNI 流行插件:
- Flannel
- Calico
- Weave
- Canal
部署 Flannel 网络
由于 k8s 已经安装好了, 可以直接使用 K8s 安装
# 安装
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 验证
kubectl get pods -n kube-system | grep flannel
节点加入集群
执行 master init 时返回的命令即可
kubeadm join 192.168.100.10:6443 --token ukdlzf.7l82o3p4qelchdxx \
--discovery-token-ca-cert-hash sha256:39def206e699bf9211619a1cfbb1d9c2fabf6c438d6481f6c2fac3983c384fe0
验证
待 flannel 安装完之后, 基础的 k8s 就已经安装完了. 然后可以来验证一下.
# 查看节点状态
kubectl get nodes
创建测试 pod
# 创建 NGINX
kubectl create deployment nginx --image=nginx:alpine
# 对外公开端口
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get pod -n default
kubectl get svc -n default
安装 Dashboard
DashBoard 是 k8s 的可视化控制台.
我在这里安装时遇到了权限错误问题, 但这个并不影响集群的使用, 如果使用 bash 直接管理没有任何问题.
获取 yaml 编排文件
# 获取 dashboard yaml 文件
wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
更新 yaml 内容和端口
sed -i 's/k8s.gcr.io/loveone/g' kubernetes-dashboard.yaml
sed -i '/targetPort:/a\ \ \ \ \ \ nodePort: 30001\n\ \ type: NodePort' kubernetes-dashboard.yaml
部署 Dashboard
kubectl create -f kubernetes-dashboard.yaml
查看相关服务运行状态
kubectl get deployment kubernetes-dashboard -n kube-system
kubectl get pods -n kube-system -o wide
kubectl get services -n kube-system
此时访问 https://192.168.100.10:30001 即可
查看 Dashboard 认证令牌
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
更换安全证书
待补充
如果你不考虑安全, 跳过令牌
- 在部署前配置跳过:
vim kubernetes-dashboard.yaml
# 修改 Deployment 下的 spec.template.spec.containers.args
# 增加 - -- enable-skip-login
未修改前
修改后
- 已部署安装方式
使用方式1修改编排文件
kubectl apply -f kubernetes-dashboard.yaml
- 没有编排文件但已部署方式
kubectl edit deployment/kubernetes-dashboard -n kube-system
按方式1 增加--enable-skip-login
参数
之后多了一个 skip 按钮
更多的
更多的还有 ingress 和其他组件安装, 在后续文章中会写出来
安装中常见问题
kubeadm安装k8s 组件controller-manager 和scheduler状态 Unhealthy
通过kubeadm安装好kubernetes v1.19.3 查看集群状态,发现组件controller-manager 和scheduler状态 Unhealthy
查看组件状态
kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Unhealthy Get http://127.0.0.1:10252/healthz: dial tcp 127.0.0.1:10252: connect: connection refused
scheduler Unhealthy Get http://127.0.0.1:10251/healthz: dial tcp 127.0.0.1:10251: connect: connection refused
etcd-0 Healthy {"health":"true"}
通过 ss 命令检查接口也未监听.
ss -ant | grep 10251
ss -ant | grep 10252
查看组件运行正常
kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
... # 其他的 pod 省略
kube-apiserver-kube-master 1/1 Running 0 23m
kube-scheduler-kube-master 1/1 Running 0 23m
... # 其他的 pod 省略
kube-scheduler和kube-controller-manager组件配置是否禁用了非安全端口
vim /etc/kubernetes/manifests/kube-scheduler.yaml
vim /etc/kubernetes/manifests/kube-controller-manager.yaml
--port=0
如果有该配置, 将其去掉.
重启 kubelet
systemctl restart kubelet
再检查组件时, 已恢复正常.
kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health":"true"}
参考解决:https://www.gjie.cn/2618.html
kubeadm join token 失效
生成需要的 token
以下命令在 master 上执行
adm_token=kubeadm token generate
kubeadm token create $adm_token --print-join-command --ttl=0
命令运行完成后会再次输出类似以下的东西
kubeadm join 192.168.100.10:6443 --token wd2yn5.9att0md62b2y5c04 \
--discovery-token-ca-cert-hash sha256:d32051303db2ccd07eb08b754e797cc58e057021a838e632cd172220cae645ec
将该命令拿到 node 上去执行即可
错误 version 不匹配
在执行时, kubeadm init 或 join 时, kubelet 的版本 与 kubeadm 执行时的版本出现不兼容将会报此错误, 将 kubeadm init --kubernetes-version 的版本与 kubelet 版本完全相同, 尽量保持 node 版本与 master 版本相同.
Connecting raw.githubusercontent.com failed
Resolving raw.githubusercontent.com (raw.githubusercontent.com)...
151.101.228.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.228.133|:443... failed: Connection refused.
这个错误是因为墙的问题, 将域名与 IP 在 hosts 中绑定上就可以了.
# hosts 文件
199.232.68.133 raw.githubusercontent.com
199.232.68.133 user-images.githubusercontent.com
199.232.68.133 avatars2.githubusercontent.com
199.232.68.133 avatars1.githubusercontent.com
140.82.114.4 github.com
199.232.69.194 github.global.ssl.fastly.net
140.82.113.9 codeload.github.com
部署组件失败, 无法下载组件
这个原因是因为 master 的 --image-url 使用的是无法使用的或 node 无法获取到基础组件.
自己摘取组件镜像到 docker 本地 image.
将以下保存到一个 sh 中. 假设名称叫:pull_k8s_img.sh
#!/bin/bash
# 注意自己的版本号
images=`kubeadm config images list --kubernetes-version=v1.19.3|awk -F '/' '{print $2}'`
for image in $images
do
docker pull keveon/$image
if [ $? -eq 0 ];then
docker tag keveon/$image k8s.gcr.io/$image
docker rmi keveon/$image
else
echo "ERROR: 下载镜像报错,$image"
fi
done
执行
chmod +x pull_k8s_img.sh && bash ./pull_k8s_img.sh