Kubernetes版本:1.27.3
准备3个云服务器,这里用的是
k8s-node2
k8s-node3
k8s-node5
时间同步
yum install ntpdate -y
ntpdate ntp.aliyun.com
开启ipvs模块
# 临时生效
modprobe br_netfilter
# 永久生效
cat > /etc/sysconfig/modules/ipvs.modules << EOF
#!/bin/sh
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
sysctl -p
更改主机名,hosts文件,ssh密钥,关闭swap
[root@k8s-node2 ~]# cat /etc/hosts
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
127.0.0.1 k8s-node2 k8s-node2
192.168.0.210 k8s-node1 k8s-node1
192.168.0.110 k8s-node2 k8s-node2
192.168.0.149 k8s-node3 k8s-node3
192.168.0.203 harbor harbor
192.168.0.238 k8s-node5 k8s-node5
# 看看是否已经存在rsa公钥
cat ~/.ssh/id_rsa.pub
# 如果不存在就创建一个新的
ssh-keygen -t rsa
# 把id_rsa.pub文件内容copy到其他机器的授权文件中
cat ~/.ssh/id_rsa.pub
# 在其他节点执行下面命令(包括worker节点)
echo "" >> ~/.ssh/authorized_keys
swapoff -a
Kubernetes配置,将IPv4流量传递到iptables
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
vm.overcommit_memory = 1
EOF
sysctl --system
如果要内网安装,需要提前准备好离线yum源
先找一个有网络的环境,或者自己创一个Linux的虚拟机;
修改yum配置(/etc/yum.conf
)中的keepcache=0
,把0改成1,然后重启系统,这样可以保存RPM包;
用yum下载好下面所有所需的软件包,如果有的包yum下载不了就只能去网上找了;
# 要安装的所有软件包
# linux常用工具
yum install -y net-tools wget vim telnet tree pstree cmake zip unzip make xz ntpdate
# k8s核心组件
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
yum install -y kubelet kubeadm kubectl
yum install -y perl-Env libcap-ng libcap bind-utils smartmontools sysstat libcap.so.1 glibc*
# 其他工具
yum install -y epel-release.noarch bash-completion.noarch
把所有下载和自己找到的rpm包都统一复制到一个文件夹里,yum下载的包一般都在/var/cache/yum/
;
按照下面的配置离线yum源部分进行操作,得到自己制作的yum源,然后用tar命令将这个文件夹打包;
# 先配置离线yum源
yum -y install createrepo
cd 到存放rpm包的文件夹
createrepo -v ./
cd ..
tar -zcvf CentOS75_my_oracle_repo.tar.gz 存放rpm包的文件夹
清除系统默认的yum源配置;
mkdir /etc/yum.back
mv /etc/yum.repos.d/* /etc/yum.back/
把刚制作的yum源打包文件传到不能联网的服务器上并解压,创建新的yum源配置,指定到传上来的本地yum源;
# 把之前制作好的yum源传到服务器,可以放在/data下
mkdir /data
cd /data
tar -zxvf CentOS75_my_oracle_repo.tar.gz
vi /etc/yum.repos.d/local.repo
[oracle]
name=oracle repo
baseurl=file:///data/my_oracle_repo
enabled=1
gpgcheck=0
priority=1
除了离线yum源,还要提前准备好离线的容器镜像
docker二进制压缩包下载地址:https://download.docker.com/linux/static/stable/
解压安装包,复制文件到/usr/bin
,复制服务启动脚本到/usr/lib/systemd/system/
,创建配置文件夹复制配置文件
将这些文件上传到/usr/local/src/
或其他目录
-rw-r--r-- 1 root root 263 Jul 13 09:17 daemon.json
-rw-r--r-- 1 root root 69624248 Jul 13 09:18 docker-24.0.4.tgz
-rw-r--r-- 1 root root 460 Jul 13 09:17 docker.service
tar -xvf docker-24.0.4.tgz
cp docker/* /usr/bin/
cp docker.service /usr/lib/systemd/system/
mkdir /etc/docker/
cp daemon.json /etc/docker/
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
data-root
: docker数据目录,要选数据盘的目录
registry-mirrors
: 镜像加速地址
insecure-registries
: 内网harbor仓库地址地址
log-opts
: 容器日志切割文件个数和单个日志文件大小
{
"data-root": "/data/docker",
"registry-mirrors": ["https://mp6fhh2b.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.0.192"],
"log-driver": "json-file",
"log-opts": {
"max-file": "10",
"max-size": "100m"
}
}
Kubeadm 是一个提供了
kubeadm init
和kubeadm join
的工具, 作为创建 Kubernetes 集群的 “快捷途径” 的最佳实践。kubeadm 通过执行必要的操作来启动和运行最小可用集群。 按照设计,它只关注启动引导,而非配置机器。同样的, 安装各种 “锦上添花” 的扩展,例如 Kubernetes Dashboard、 监控方案、以及特定云平台的扩展,都不在讨论范围内。
相反,我们希望在 kubeadm 之上构建更高级别以及更加合规的工具, 理想情况下,使用 kubeadm 作为所有部署工作的基准将会更加易于创建一致性集群。
添加阿里云k8s的yum源
kubernetes镜像_kubernetes下载地址_kubernetes安装教程-阿里巴巴开源镜像站 (aliyun.com)
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 kubelet && systemctl start kubelet
检查是否安装runc,一般docker或containerd里都有
[root@k8s-node2 ~]# runc -v
runc version 1.1.7
commit: v1.1.7-0-g860f061
spec: 1.0.2-dev
go: go1.20.5
libseccomp: 2.5.1
生成一个初始化的yaml文件,查看这个版本的kubeadm所需的镜像版本
[root@k8s-node2 ~]# kubeadm config print init-defaults > kubeadm.yaml
[root@k8s-node2 ~]# kubeadm config images list --config kubeadm.yaml
registry.aliyuncs.com/google_containers/kube-apiserver:v1.27.0
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.27.0
registry.aliyuncs.com/google_containers/kube-scheduler:v1.27.0
registry.aliyuncs.com/google_containers/kube-proxy:v1.27.0
registry.aliyuncs.com/google_containers/pause:3.9
registry.aliyuncs.com/google_containers/etcd:3.5.7-0
registry.aliyuncs.com/google_containers/coredns:v1.10.1
在V1.24起的版本的 kubelet 就彻底移除了dockershim,改为默认使用Containerd,所以要使用 cri-dockerd适配器来将Docker Engine与 Kubernetes 集成
https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#docker
cri-docker 是一个适配器,它允许 kubelet 通过 CRI 接口与 docker 通信3。cri-docker 也接受一个命令行参数来指定 pause 容器的镜像,即 --pod-infra-container-image 3。如果不指定这个参数,cri-docker 会使用默认的镜像 k8s.gcr.io/pause:3.1 3
二进制包下载地址:https://github.com/Mirantis/cri-dockerd/releases
将这些文件上传到/usr/local/src/
或其他目录
-rw-r--r-- 1 root root 13M Jul 13 11:54 cri-dockerd-0.3.4.amd64.tgz
-rw-r--r-- 1 root root 1.4K Jul 13 12:10 cri-docker.service
解压安装,复制配置文件
tar xvf cri-dockerd-0.3.4.amd64.tgz
cp -i ./cri-dockerd/cri-dockerd /usr/local/bin/
cp -i ./cri-docker.s* /usr/lib/systemd/system/
启动配置文件的内容,要查看刚下载的kubeadm需要哪个版本的pause容器
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket
[Service]
Type=notify
ExecStart=/usr/local/bin/cri-dockerd --container-runtime-endpoint fd:// --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# ExecStart这个版本要看对应的kubeadm要使用的版本,仓库地址也最好换成国内的阿里云
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
pod-infra-container-image 是一个 kubelet 的参数,用来指定 pod 中的 pause 容器的镜像1。pause 容器是一个特殊的容器,它用来创建和维护 pod 的网络和 IPC 命名空间,以及清理僵尸进程2。pause 容器的镜像通常是一个简单的二进制文件,它只执行一个无限循环的操作
启动
systemctl daemon-reload && systemctl enable --now cri-docker
systemctl status cri-docker
这一步最关键,最容易翻车
命令部署和yaml部署两种选其中一种
kubeadm init --node-name=k8s-master --image-repository=registry.aliyuncs.com/google_containers --cri-socket=unix:///var/run/cri-dockerd.sock --apiserver-advertise-address=master服务器ip地址 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12
当出现这个就说明没有翻车,可以继续安装,如果有错误提示就要先解决故障
复制最下面的kubeadm join
一串命令找位置记录一下(现在不用),这是后续需要将其他节点加入集群的命令,除了这个以外,其他的参数有
--image-repository=registry.aliyuncs.com/google_containers # 将下载容器镜像源替换为阿里云,否则因为网络原因会导致镜像拉不下来,一定会执行不成功。
--cri-socket=unix:///var/run/cri-dockerd.sock # 这是指定容器运行时,因为containerd也是Docker的组件之一,下载Docker会一并将containerd下载下来,在执行初始化时当Kubernetes检测到有多个容器运行时环境,就必须要手动选择一个。这里也可以看出containerd实际上比Docker更轻量得多。
--apiserver-advertise-address=192.168.56.50 # 为API server设置广播地址,这里选择本机的ipv4地址,这里不希望API SERVER设置在其他node上的话就不要改为其他地址。
--pod-network-cidr=10.244.0.0/16 # 指明 pod 网络可以使用的 IP 地址段,暂时不清楚的可以先不管就用这个值。
--service-cidr=10.96.0.0/12 # 为服务的虚拟 IP 地址另外指定 IP 地址段,暂时不清楚的可以先不管就用这个值。
在主Master节点继续执行:
# 非root用户请执行
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
# root用户直接执行
$ export KUBECONFIG=/etc/kubernetes/admin.conf # 临时生效,重启后失效,不推荐。
$ echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile # 永久生效,执行kubeadm reset后再次init也无需再次执行这条命令
$ source ~/.bash_profile # 执行永久生效命令之后需要source一下使其生效
$ echo $KUBECONFIG # 检测配置是否生效
/etc/kubernetes/admin.conf
找到在刚创建了一个用来查看软件包的kubeadm.yaml
下载Kubernetes核心组件
修改一下这个配置文件
advertiseAddress
::Master服务器的IP地址criSocket
:容器运行时的路径imageRepository
:镜像源地址,改成阿里云podSubnet
:用来分配给集群中Pod的IP地址范围,serviceSubnet 和 podSubnet 不能重叠或者包含集群节点的 IP 地址serviceSubnet
:用来分配给集群中的服务(Service)的IP地址范围,serviceSubnet 和 podSubnet 不能重叠或者包含集群节点的 IP 地址apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.0.110
bindPort: 6443
nodeRegistration:
criSocket: unix:///var/run/cri-dockerd.sock
imagePullPolicy: IfNotPresent
name: k8s-node2
taints: null
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.27.0
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
配置好了以后执行命令开始初始化
kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification
Flannel 是一个为 Kubernetes 设计的简单易用的网络组件1。它可以在集群中的多个节点之间建立一个 IPv4 的网络1。它不负责控制容器如何与主机网络连接,只负责在主机之间转发流量1。它可以使用多种后端机制来实现网络通信,比如 VXLAN 和各种云平台的集成
Flannel要在所有节点都安装上
下载两个文件,一个是CNI插件,一个是Flannel的yml文件
如果是高版本的CNI插件,里面少了个flannel的文件,这个文件又只有低于1.0版本才有,这个要注意下
Releases · containernetworking/plugins (github.com)
Release v0.22.0 · flannel-io/flannel · GitHub
-rw-r--r-- 1 root root 45338194 Jul 18 16:52 cni-plugins-linux-amd64-v1.3.0.tgz
-rw-r--r-- 1 root root 3357992 Jul 18 18:15 flannel
-rw-r--r-- 1 root root 4459 Jul 18 16:51 kube-flannel.yml
mkdir -p /opt/cni/bin
tar -C /opt/cni/bin -xzf cni-plugins-linux-amd64-v1.3.0.tgz
mkdir /run/flannel
cat <<EOF > /run/flannel/subnet.env
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
EOF
kubectl apply -f kube-flannel.yml # 为Kubernetes配置flannel网络插件
#输出内容
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
将主节点配置文件复制到其他节点
cp /etc/kubernetes/admin.conf root@k8s-node3:/etc/kubernetes/
cp /etc/kubernetes/admin.conf root@k8s-node5:/etc/kubernetes/
在所有节点添加环境变量
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile # 不要忘记将admin.conf加入环境变量,这里直接使用永久生效。
source ~/.bash_profile
把之前初始化成功的时候得到的命令找到,加上设置自己这边容器运行时路径的参数,比如这样
kubeadm join 192.168.0.110:6443 --token vn1kky.ikxktdgqv0ntmof1 \
--discovery-token-ca-cert-hash sha256:b416f1d5d388fec1133b7c3c8960c84f27b51d35efbc8b8e0fac223f649ba73d --cri-socket=unix:///var/run/cri-dockerd.sock
如果出现如下输出就说明问题不大了
preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
检查一下节点和od状态
[root@k8s-node2 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-node2 Ready control-plane 3h41m v1.27.3
k8s-node3 Ready 166m v1.27.3
k8s-node5 Ready 165m v1.27.3
[root@k8s-node2 ~]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-flannel kube-flannel-ds-b2t58 1/1 Running 1 (111m ago) 166m
kube-flannel kube-flannel-ds-rfs25 1/1 Running 2 (111m ago) 165m
kube-flannel kube-flannel-ds-tkqxk 1/1 Running 1 (111m ago) 177m
kube-system coredns-7bdc4cb885-8g5dv 1/1 Running 1 (111m ago) 3h41m
kube-system coredns-7bdc4cb885-qqp4h 1/1 Running 1 (111m ago) 3h41m
kube-system etcd-k8s-node2 1/1 Running 1 (111m ago) 3h41m
kube-system kube-apiserver-k8s-node2 1/1 Running 1 (111m ago) 3h41m
kube-system kube-controller-manager-k8s-node2 1/1 Running 1 (111m ago) 3h41m
kube-system kube-proxy-5n8sm 1/1 Running 1 (111m ago) 166m
kube-system kube-proxy-62tcq 1/1 Running 2 (111m ago) 165m
kube-system kube-proxy-nllwh 1/1 Running 1 (111m ago) 3h41m
kube-system kube-scheduler-k8s-node2 1/1 Running 1 (111m ago) 3h41m
随便启动一个Nginx的Pod测试一下
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
[root@k8s-node2 ~]# kubectl apply -f test.yml
[root@k8s-node2 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 115m
Pod要能正常Running才说明没有问题了
到这里为止,三个节点的K8s已经完成部署了,为了方便运维还可以部署一些其他工具
# 在所有节点上操作
yum install -y epel-release.noarch bash-completion.noarch
kubectl completion bash >/etc/bash_completion.d/kubectl
退出并重新登录shell会发现kubectl可以进行补全了
如果最后节点状态不是Ready,是NotReady,且很长时间都没有变成Ready,那就要排查下
# 查看kubelet日志
journalctl -xeu kubelet
journalctl -f -u kubelet
# 查看Node
kubectl describe node 节点名
如果Pod状态不是Running说明也有问题,需要查看一下Pod的详细状态
kubectl describe pod pod名
您可以使用
kubectl help [command\]
来查看每个命令的详细用法和选项](https://kubernetes.io/zh/docs/reference/kubectl/)1。您也可以参考以下网址来学习更多关于 kubectl 的知识
基本命令:用于操作 Kubernetes 集群中的基本资源对象,如 Pod、Service、Deployment 等。例如:
kubectl create
:创建一个或多个资源对象kubectl get
:列出一个或多个资源对象kubectl describe
:显示一个或多个资源对象的详细信息kubectl delete
:删除一个或多个资源对象高级命令:用于操作 Kubernetes 集群中的高级功能,如标签、注解、配置文件等。例如:
kubectl apply
:通过配置文件或标准输入创建或更新资源对象kubectl label
:更新一个或多个资源对象的标签kubectl annotate
:更新一个或多个资源对象的注解kubectl edit
:通过编辑器修改一个或多个资源对象集群管理命令:用于管理 Kubernetes 集群的状态和配置,如节点、上下文、证书等。例如:
kubectl cordon
:将一个节点标记为不可调度kubectl uncordon
:将一个节点标记为可调度kubectl drain
:安全地清空一个节点上的所有 Podkubectl config
:管理 kubeconfig 文件