一、准备基础环境
1、主机名配置
#master节点: hostnamectl set-hostname k8s-master
echo k8s-master > /etc/hosts
#node1节点: hostnamectl set-hostname k8s-node1
echo k8s-node1 > /etc/hosts
#node2节点: hostnamectl set-hostname k8s-node2
echo k8s-node2> /etc/hosts
2、环境配置:
#修改/etc/hosts文件
cat >> /etc/hosts << EOF
192.168.58.130 k8s-master
192.168.58.131 k8s-node1
192.168.58.132 k8s-node2
EOF
#关闭防火墙和selinux
systemctl stop firewalld && systemctl disable firewalld
sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config && setenforce 0
#关闭swap
swapoff -a
cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab
3、配置时间同步
配置master节点:
#安装chrony:
yum install -y chrony
#注释默认ntp服务器
sed -i 's/^server/#&/' /etc/chrony.conf
#指定上游公共 ntp 服务器,并允许其他节点同步时间
cat >> /etc/chrony.conf << EOF
server 0.asia.pool.ntp.org iburst
server 1.asia.pool.ntp.org iburst
server 2.asia.pool.ntp.org iburst
server 3.asia.pool.ntp.org iburst
allow all
EOF
#重启chronyd服务并设为开机启动:
systemctl enable chronyd && systemctl restart chronyd
#开启网络时间同步功能
timedatectl set-ntp true
配置node节点:
#安装chrony:
yum install -y chrony
#注释默认服务器
sed -i 's/^server/#&/' /etc/chrony.conf
#指定内网 master节点为上游NTP服务器
echo server 192.168.58.130 iburst >> /etc/chrony.conf
#重启服务并设为开机启动:
systemctl enable chronyd && systemctl restart chronyd
4、修改iptables相关参数
RHEL / CentOS 7上的一些用户报告了由于iptables被绕过而导致流量路由不正确的问题。创建/etc/sysctl.d/k8s.conf文件,添加如下内容:
cat <<EOF > /etc/sysctl.d/k8s.conf
vm.swappiness = 0
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
# 使配置生效
modprobe br_netfilter
sysctl -p /etc/sysctl.d/k8s.conf
5、加载ipvs相关模块
由于ipvs已经加入到了内核的主干,所以为kube-proxy开启ipvs的前提需要加载以下的内核模块:
在所有的Kubernetes节点执行以下脚本:
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
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
上面脚本创建了/etc/sysconfig/modules/ipvs.modules文件,保证在节点重启后能自动加载所需模块。 使用lsmod | grep -e ip_vs -e nf_conntrack_ipv4命令查看是否已经正确加载所需的内核模块。
接下来还需要确保各个节点上已经安装了ipset软件包。 为了便于查看ipvs的代理规则,最好安装一下管理工具ipvsadmyum install ipset ipvsadm -y
5、安装Docker
配置docker源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装docker yum install docker-ce docker-ce-cli containerd.io
yum install docker-ce
#需要去下载kube-apiserver、kube-scheduler、kube-controller-manager
对访问到国外的镜像网站做代理,如果从本地下载的镜像则不做代理:添加在12行:
修改docker 启动文件
vim /usr/lib/systemd/system/docker.service
#配置docker 镜像加速器 registry.cn-chengdu.aliyuncs.com
cat <<EOF> /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": ["https://396cwanx.mirror.aliyuncs.com"]
}
EOF
添加变量:
[Service]
Environment="HTTPS_PROXY=http://www.ik8s.io:10080"
Environment="NO_PROXY=127.0.0.0/8,192.168.58.0/24"
再加载
systemctl daemon-reload
systemctl restart docker
6、配置kubernetes的源
#配置kubernetes.repo的源,由于官方源国内无法访问,这里使用阿里云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
#在所有节点上安装指定版本 kubelet、kubeadm 和 kubectl
yum install -y kubeadm-1.28.1 kubelet-1.28.1 kubectl-1.28.1
systemctl enable kubelet #不需要启动kubelet
二、部署kubernetes环境
1、部署master节点
初始化节点
kubeadm init \
--apiserver-advertise-address=192.168.58.130 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.28.1 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16
报错1:
1、忽略Swap 启动:
[root@node1 ~]# vim /etc/sysconfig/kubelet
[root@node1 ~]# cat /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
也可以在初始化中加入参数:--ignore-preflight-errors=Swap
#关闭swap
swapoff -a
cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab
2、报错:
报错:[ERROR CRI]: container runtime is not running: output: time="2023-09-04T14:54:00+08:00" level=fatal msg="validate service connection: CRI v1 runtime API is not implemented for endpoint \"unix:///var/run/containerd/containerd.sock\": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService"
, error: exit status 1
解决方案:rm -rf /etc/containerd/config.toml && systemctl restart containerd
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG=/etc/kubernetes/admin.conf
kubeadm join 192.168.58.130:6443 --token zp6ikt.3f6ujjr490i501fu \
--discovery-token-ca-cert-hash sha256:b0910b831188c67f5bdb9d7d63af90bd0861311cba6a3179a5502b4b12c284f2
#如果token失效,master重新生成:
kubeadm token create --print-join-command
2、master部署网络插件
要让 Kubernetes Cluster 能够工作,必须安装 Pod 网络,否则 Pod 之间无法通信。
Kubernetes 支持多种网络方案,这里我们使用 flannel
执行如下命令部署 flannel:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
3、kube-dns 解析配置
vim /etc/sysctl.d/k8s.conf
[root@node1 ~]# cat /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
sysctl --system |grep net.bridge.bridge
sysctl --system |grep ip_forward
wget -O - -q http://nginx:80
4、部署worker节点
#执行以下命令将节点接入集群,接入前不需要启动kubelet
kubeadm join 192.168.58.130:6443 --token zp6ikt.3f6ujjr490i501fu \
--discovery-token-ca-cert-hash sha256:b0910b831188c67f5bdb9d7d63af90bd0861311cba6a3179a5502b4b12c284f2
#如果执行kubeadm init时没有记录下加入集群的命令,可以通过以下命令重新创建
kubeadm token create --print-join-command
如果安装出错:
kubeadmin reset
再重新接入
安装报错:
报错:[ERROR CRI]: container runtime is not running: output: time="2023-09-04T14:54:00+08:00" level=fatal msg="validate service connection: CRI v1 runtime API is not implemented for endpoint \"unix:///var/run/containerd/containerd.sock\": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService"
, error: exit status 1
解决方案:rm -rf /etc/containerd/config.toml && systemctl restart containerd
5、测试组件
#首先验证kube-apiserver, kube-controller-manager, kube-scheduler, pod network 是否正常:
部署一个 Nginx Deployment,包含2个Pod
#通过deployment 创建pods
kubectl create deployment nginx --image=nginx:alpine
[root@node1 docker]# kubectl create deploy nginx --image=nginx:alpine --replicas=3 --dry-run -o yaml
W0920 14:32:48.749858 72143 helpers.go:692] --dry-run is deprecated and can be replaced with --dry-run=client.
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:alpine
name: nginx
resources: {}
status: {}
#扩容副本数:
kubectl scale deployment nginx --replicas=2
[root@node1 docker]# kubectl get pods -l app=nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-b4ccb96c6-qxc52 1/1 Running 0 6m22s 10.244.1.2 node2 <none> <none>
nginx-b4ccb96c6-zmrb8 1/1 Running 0 6m22s 10.244.2.4 node3 <none> <none>
三、PodS Controller组件
1、以 NodePort 方式对外提供服务(Service)
[root@node1 ~]# kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed
[root@node1 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4h35m
nginx NodePort 10.99.101.137 <none> 80:30611/TCP 6s
#生成yaml格式数据
[root@node1 ~]# kubectl expose deployment nginx --port=80 --type=NodePort --dry-run -o yaml
W0920 14:36:50.660752 73203 helpers.go:692] --dry-run is deprecated and can be replaced with --dry-run=client.
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: NodePort
status:
loadBalancer: {}
2、Deployment(副本控制器包含)
kubectl create deployment nginx-deploy --image=nginx:1.14-alpine --port=80 --target-port=80 --replicas=2
kubectl create deployment nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1
kubectl expose pods nginx-deploy --name=nginx --port=80 --target-port=80 --protocol=TCP
kubectl describe svc nginx
kubectl get pods --show-labels
kubectl scale --replicas=3 deployment nginx-deploy 手动改变副本数
控制名称 容器名
kubectl set image deployment nginx-deploy nginx=nginx:1.15-alpine 升级版本
[root@node1 ~]# kubectl set image deployment nginx-deploy nginx=nginx:1.15-alpine
deployment.apps/nginx-deploy image updated
[root@node1 ~]# kubectl rollout status deployment nginx-deploy 查看升级进度
Waiting for deployment "nginx-deploy" rollout to finish: 1 out of 2 new replicas have been updated...
kubectl rollout undo deployment nginx 回滚到上一个版本
iptables -vnL 生成规则
iptables -vnL -t nat
外网访问K8S service 使用命令:
kubectl edit svc nginx
其中片段
spec:
clusterIP: 10.107.177.24
clusterIPs:
- 10.107.177.24
externalTrafficPolicy: Cluster
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- nodePort: 30937
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-deploy
sessionAffinity: None
type: NodePort 这个值 ClusterIP修改为NodePort
查看结果
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d
nginx NodePort 10.107.177.24 <none> 80:30937/TCP 6h6m
3、YAML管理Pods
YMAL
查看分类 kubectl api-versions
#查看各个字段帮助说明
kubectl explain pods.spec.containers 查看yaml字段解释
kubectl exec demo-pod myapp -it -- sh 查看内部情况
kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8 --dry-run -o yaml >tomcat6.yaml
kubectl expose deployment tomcat6 --port 8080 --target-port=8080 --type=NodePort --dry-run -o yaml > tomcat6-svc.yaml
kubectl create deployment tomcat9 --image=tomcat:9.0.80 --dry-run -o yaml>tomcat9.yaml
kubectl expose deployment tomcat9 --port 8080 --target-port=8080 --type=NodePort --dry-run -o yaml > tomcat9-svc.yaml
需要拷贝数据
kubectl exec tomcat9-5b586c5f57-lgm7c -it -- /bin/bash
cp -R webapps.dist/. webapps/
[root@node1 nginx-deploy]# cat nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
namespace: default
labels:
controller: deploy #deploy 标签
spec:
replicas: 4
revisionHistoryLimit: 8 #保留历史版本,默认是10
paused: false #暂停部署,默认是false
progressDeadlineSeconds: 600 #部署超时时间(s),默认是600
strategy:
type: RollingUpdate #滚动更新策略 Recreate:在创建出新的pod之前会先杀掉所有已存在的pod;
RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本pod
rollingUpdate:
maxSurge: 25% 用来指定在升级过程中不可用pod的最大数量,默认为25%
#maxUnavaliable: 25%
maxUnavailable: 0 用来指定在升级过程中可以超过期望的pod的最大数量,默认为25%
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
kubectl apply -f nginx-deploy.yaml 创建或者更新 根据yaml清单配置
#根据deploy 标签筛选
kubectl get deploy --show-labels -o wide -l controller=deploy
kubectl explain deploy.spec.template.metadata
修改副本数(动态)
kubectl scale deploy nginx-deploy --replicas=4
kubectl edit deploy nginx-deploy 修改 运行中的YAML数据
kubectl set image deploy nginx-deploy nginx=nginx:1.17.2 && kubectl rollout pause deploy nginx-deploy 按照设置的升级规则动态滚动升级并暂停
kubectl rollout resume deploy nginx-deploy
rollout 后参数:pause(暂停) resume(继续执行更新) history(查看历史版本) status 查看状态 undo [--to-version= 1] 退回上一个版本或者指定版本
kubectl get deploy nginx-deploy -o yaml
查看历史版本:kubectl rollout history deploy nginx-deploy
kubectl rollout history deploy nginx-deploy --revision=2
kubectl set image deploy nginx-deploy nginx=nginx:1.17.1 && kubectl rollout status deploy nginx-deploy
4、配置kube-proxy的负载底层模式:
默认负载底层模式为iptables
更改service负载代理模式的方法
(1)加入内核参数
modprobe – ip_vs
modprobe – ip_vs_rr
modprobe – ip_vs_wrr
modprobe – ip_vs_sh
modprobe – nf_conntrack_ipv4
(2)查看是否加入成功
lsmod|grep ip_vs
(3)修改proxy中的configmap
kubectl edit configmap kube-proxy -n kube-system
把mode: ""改为mode: “ipvs” 默认走iptables,想走ipvs只能自己修改
(4)改完并不是立即生效,需要重启proxy的pod,每个节点都会对应一个proxy可以先重启修改完毕的节点的proxy
kubectl get pod -n kube-system -o wide | grep proxy
#查看proxy对应的node节点或者master节点
kubectl delete pod -n kube-system kube-proxy-zqx2l
kubectl get pod -n kube-system -o wide | grep proxy
查看是否重启成功
(5)安装ipvxadm并查看是否修改成功
yum install ipvsadm
ipvsadm -L -n