Bootstrap

Ubuntu 22.04.3安装kubernetes v1.26.3

环境准备

1、主机准备
VMware Workstation安装3台虚拟机
网卡模式为NAT模式


2、版本说明
系统版本:ubuntu-22.04.3-desktop-amd64
Kubernetes版本:v1.26.3
容器运行时版本:containerd v1.6.20
客户端版本:nerdctl-1.3.0
CNI插件版本:cni-plugins-linux-amd64-v1.2.0

系统初始化(所有节点)

1、关闭防火墙
Ubuntu 自带一个配置防火墙配置工具,称为 UFW。确保防火墙状态为inactive

# ufw disable
# ufw status
Status: inactive

2、关闭交换分区
通过kubeadm部署集群时会检查当前主机是否禁用了Swap设备,否则会导致部署失败。

# swapoff -a
# free
root@master:/home/user# free
               total        used        free      shared  buff/cache   available
Mem:         3964464     1420180     1345660       15060     1198624     2280516
Swap:              0           0           0

3、配置时间同步

# apt install chrony
# systemctl start chrony.service  
检查时间是否同步
# chronyc tracking -V
Reference ID    : CA760182 (time.neu.edu.cn)
Stratum         : 2
Ref time (UTC)  : Mon Dec 18 11:13:49 2023
System time     : 0.000578838 seconds slow of NTP time
Last offset     : -0.000388255 seconds
RMS offset      : 0.000761426 seconds
Frequency       : 5.403 ppm fast
Residual freq   : -0.105 ppm
Skew            : 14.889 ppm
Root delay      : 0.023036918 seconds
Root dispersion : 0.003026418 seconds
Update interval : 64.8 seconds
Leap status     : Normal

4、设置host映射和主机名

hostnamectl set-hostname master
cat >> /etc/hosts << EOF
192.168.0.174   master
192.168.0.175   node1
192.168.0.176   node2
EOF

安装容器运行时、客户端工具和CNI插件

1、本示例通过以下脚本源码安装,安装包和脚本获取如下
链接:https://pan.baidu.com/s/1r9wS8OUj-OQxtSId-KN3pQ?pwd=hd3i
提取码:hd3i

#!/bin/bash
DIR=`pwd`
PACKAGE_NAME="docker-20.10.19.tgz"
DOCKER_FILE=${DIR}/${PACKAGE_NAME}
#read -p "请输入使用docker server的普通用户名称,默认为docker:" USERNAME
if test -z ${USERNAME};then
  USERNAME=docker
fi
centos_install_docker(){
  grep "Kernel" /etc/issue &> /dev/null
  if [ $? -eq 0 ];then
    /bin/echo  "当前系统是`cat /etc/redhat-release`,即将开始系统初始化、配置docker-compose与安装docker" && sleep 1
    systemctl stop firewalld && systemctl disable firewalld && echo "防火墙已关闭" && sleep 1
    systemctl stop NetworkManager && systemctl disable NetworkManager && echo "NetworkManager" && sleep 1
    sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux && setenforce  0 && echo "selinux 已关闭" && sleep 1
    \cp ${DIR}/limits.conf /etc/security/limits.conf 
    \cp ${DIR}/sysctl.conf /etc/sysctl.conf
    /bin/tar xvf ${DOCKER_FILE}
    \cp docker/*  /usr/local/bin
    mkdir /etc/docker && \cp daemon.json /etc/docker

\cp containerd.service /lib/systemd/system/containerd.service
\cp docker.service  /lib/systemd/system/docker.service
\cp docker.socket /lib/systemd/system/docker.socket

\cp ${DIR}/docker-compose-Linux-x86_64_1.28.6 /usr/bin/docker-compose

groupadd docker && useradd docker -s /sbin/nologin -g docker
id -u  ${USERNAME} &> /dev/null
if [ $? -ne 0 ];then
  useradd ${USERNAME}
  usermod ${USERNAME} -G docker
else 
  usermod ${USERNAME} -G docker
fi
docker_install_success_info
  fi
}

ubuntu_install_docker(){
  grep "Ubuntu" /etc/issue &> /dev/null
  if [ $? -eq 0 ];then
    /bin/echo  "当前系统是`cat /etc/issue`,即将开始系统初始化、配置docker-compose与安装docker" && sleep 1
    \cp ${DIR}/limits.conf /etc/security/limits.conf
    \cp ${DIR}/sysctl.conf /etc/sysctl.conf
    
/bin/tar xvf ${DOCKER_FILE}
\cp docker/*  /usr/local/bin 
mkdir /etc/docker && \cp daemon.json /etc/docker

\cp containerd.service /lib/systemd/system/containerd.service
\cp docker.service  /lib/systemd/system/docker.service
\cp docker.socket /lib/systemd/system/docker.socket

\cp ${DIR}/docker-compose-Linux-x86_64_1.28.6 /usr/bin/docker-compose

groupadd docker && useradd docker -r -m -s /sbin/nologin -g docker
id -u  ${USERNAME} &> /dev/null
if [ $? -ne 0 ];then
  groupadd  -r  ${USERNAME}
  useradd -r -m -s /bin/bash -g ${USERNAME} ${USERNAME}
  usermod ${USERNAME} -G docker
else
  usermod ${USERNAME} -G docker
fi  
docker_install_success_info
  fi
}

ubuntu_install_containerd(){
  DIR=`pwd`
  PACKAGE_NAME="containerd-1.6.20-linux-amd64.tar.gz"
  CONTAINERD_FILE=${DIR}/${PACKAGE_NAME}
  NERDCTL="nerdctl-1.3.0-linux-amd64.tar.gz"
  CNI="cni-plugins-linux-amd64-v1.2.0.tgz"
  RUNC="runc.amd64"
  
  mkdir -p /etc/containerd /etc/nerdctl
  tar xvf ${CONTAINERD_FILE} &&  cp bin/* /usr/local/bin/
  \cp runc.amd64   /usr/bin/runc && chmod  a+x /usr/bin/runc
  \cp config.toml  /etc/containerd/config.toml
  \cp containerd.service /lib/systemd/system/containerd.service

  #CNI 
  mkdir  /opt/cni/bin -p 
  tar xvf ${CNI}  -C  /opt/cni/bin/

  #nerdctl
  tar xvf ${NERDCTL}  -C /usr/local/bin/
  \cp nerdctl.toml /etc/nerdctl/nerdctl.toml

  containerd_install_success_info
}

containerd_install_success_info(){
    /bin/echo "正在启动containerd server并设置为开机自启动!" 
    #start containerd  service
    systemctl daemon-reload && systemctl  restart  containerd && systemctl  enable containerd
    /bin/echo "containerd is:" `systemctl  is-active  containerd`
    sleep 0.5 && /bin/echo "containerd server安装完成,欢迎进入containerd的容器世界!" && sleep 1
}

docker_install_success_info(){
    /bin/echo "正在启动docker server并设置为开机自启动!" 
    systemctl  enable containerd.service && systemctl  restart containerd.service
    systemctl  enable docker.service && systemctl  restart docker.service
    systemctl  enable docker.socket && systemctl  restart docker.socket
    sleep 0.5 && /bin/echo "docker server安装完成,欢迎进入docker世界!" && sleep 1
}

usage(){
    echo "使用方法为[shell脚本  containerd|docker]"
}

main(){
  RUNTIME=$1
  case ${RUNTIME}  in 
    docker)
      centos_install_docker  
      ubuntu_install_docker
      ;;
    containerd)
      ubuntu_install_containerd
      ;;
    *)
      usage;
    esac;
}

main $1

2、安装和验证

# tar xvf runtime-docker20.10.19-containerd1.6.20-binary-install.tar.gz
# bash runtime-install.sh containerd
# containerd -v
containerd github.com/containerd/containerd v1.6.20 2806fc1057397dbaeefbea0e4e17bddfbd388f38
# nerdctl -v
nerdctl version 1.3.0

3、修改containerd配置文件
修改启用cgroup driver为systemd(kubelet需要让docker容器引擎使用systemd作为CGroup的驱动,其默认值为cgroupfs)。
修改拉取pause镜像地址为国内地址。

# mkdir /etc/containerd
# containerd config default > /etc/containerd/config.toml
# vim /etc/containerd/config.toml
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.7" 
 [plugins."io.containerd.grpc.v1.cri".registry.mirrors] 
 [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] 
 endpoint = ["https://9916w1ow.mirror.aliyuncs.com"] 

# containerd config dump | grep -i -E "systemd|mirror"
systemd_cgroup = false
        SystemdCgroup = true
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
      endpoint = ["https://9916w1ow.mirror.aliyuncs.com"]

# systemctl restart containerd && systemctl enable containerd

安装kubeadm、kubectl、kubelet(所有节点)

root@k8s-master1:~# apt-get update && apt-get install -y apt-transport-https -y
root@k8s-node1:~# apt-get update && apt-get install -y apt-transport-https -y
root@k8s-node2:~# apt-get update && apt-get install -y apt-transport-https -y
root@k8s-master1:~# curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
root@k8s-node1:~# curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
root@k8s-node2:~# curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
root@k8s-master1:~# cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
root@k8s-node1:~# cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
root@k8s-node2:~# cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
root@k8s-master1:~# apt-get update && apt-cache madison kubeadm
root@k8s-node1:~# apt-get update && apt-cache madison kubeadm
root@k8s-node2:~# apt-get update && apt-cache madison kubeadm
root@k8s-master1:~# apt-get install -y kubeadm=1.26.3-00 kubectl=1.26.3-00 kubelet=1.26.3-00
root@k8s-node1:~# apt-get install -y kubeadm=1.26.3-00 kubectl=1.26.3-00 kubelet=1.26.3-00

下载kubernetes镜像

root@k8s-master1:~# kubeadm config images list --kubernetes-version v1.26.3
root@k8s-master1:~# vim images-down.sh
#!/bin/bash
nerdctl pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.26.3
nerdctl pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controllermanager:v1.26.3
nerdctl pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.26.3
nerdctl pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.26.3
nerdctl pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9
nerdctl pull registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.6-0
nerdctl pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.9.3
root@k8s-master1:~# bash images-down.sh

内核参数优化

1、修改内核参数配置文件

	root@k8s-master1:~# cat /etc/sysctl.conf
	net.ipv4.ip_forward=1
	vm.max_map_count=262144
	kernel.pid_max=4194303
	fs.file-max=1000000
	net.ipv4.tcp_max_tw_buckets=6000
	net.netfilter.nf_conntrack_max=2097152
	net.bridge.bridge-nf-call-ip6tables = 1
	net.bridge.bridge-nf-call-iptables = 1
	vm.swappiness=0

2、内核模块开机挂载

root@k8s-master1:~#vim /etc/modules-load.d/modules.conf
ip_vs
ip_vs_lc
ip_vs_lblc
ip_vs_lblcr
ip_vs_rr
ip_vs_wrr
ip_vs_sh
ip_vs_dh
ip_vs_fo
ip_vs_nq
ip_vs_sed
ip_vs_ftp
ip_vs_sh
ip_tables
ip_set
ipt_set
ipt_rpfilter
ipt_REJECT
ipip
xt_set
br_netfilter
nf_conntrack
overlay

3、验证内核模块与内存参数

root@k8s-master1:~# lsmod | grep br_netfilter
br_netfilter 32768 0
bridge 307200 1 br_netfilter
root@k8s-master1:~# sysctl -a | grep bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 1

kubernetes集群初始化(主节点)

root@k8s-master1:~# kubeadm init --apiserver-advertise-address=11.0.1.131 --apiserver-bind-port=6443 --kubernetes-version=v1.26.3 --pod-network-cidr=10.100.0.0/16 --service-cidr=10.200.0.0/16 --service-dns-domain=cluster.local --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers --ignore-preflight-errors=swap
root@k8s-master1:~# mkdir -p $HOME/.kube
root@k8s-master1:~# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
root@k8s-master1:~# sudo chown $(id -u):$(id -g) $HOME/.kube/config

#参数说明
  --apiserver-advertise-address string   设置 apiserver 绑定的 IP.
  --apiserver-bind-port int32            设置apiserver 监听的端口. (默认 6443)
  --apiserver-cert-extra-sans strings    api证书中指定额外的Subject Alternative Names (SANs) 可以是IP 也可以是DNS名称。 证书是和SAN绑定的。
  --cert-dir string                      证书存放的目录 (默认 "/etc/kubernetes/pki")
  --certificate-key string               kubeadm-cert secret 中 用于加密 control-plane 证书的key
  --config string                        kubeadm 配置文件的路径.
  --cri-socket string                    CRI socket 文件路径,如果为空 kubeadm 将自动发现相关的socket文件; 只有当机器中存在多个 CRI  socket 或者 存在非标准 CRI socket 时才指定.
  --dry-run                              测试,并不真正执行;输出运行后的结果.
  --feature-gates string                 指定启用哪些额外的feature 使用 key=value 对的形式。
  --help  -h                             帮助文档
  --ignore-preflight-errors strings      忽略前置检查错误,被忽略的错误将被显示为警告. 例子: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.
  --image-repository string              选择拉取 control plane images 的镜像repo (default "k8s.gcr.io")
  --kubernetes-version string            选择K8S版本. (default "stable-1")
  --node-name string                     指定node的名称,默认使用 node 的 hostname.
  --pod-network-cidr string              指定 pod 的网络, control plane 会自动将 网络发布到其他节点的node,让其上启动的容器使用此网络
  --service-cidr string                  指定service 的IP 范围. (default "10.96.0.0/12")
  --service-dns-domain string            指定 service 的 dns 后缀, e.g. "myorg.internal". (default "cluster.local")
  --skip-certificate-key-print           不打印 control-plane 用于加密证书的key.
  --skip-phases strings                  跳过指定的阶段(phase)
  --skip-token-print                     不打印 kubeadm init 生成的 default bootstrap token 
  --token string                         指定 node 和control plane 之间,简历双向认证的token ,格式为 [a-z0-9]{6}\.[a-z0-9]{16} - e.g. abcdef.0123456789abcdef
  --token-ttl duration                   token 自动删除的时间间隔。 (e.g. 1s, 2m, 3h). 如果设置为 '0', token 永不过期 (default 24h0m0s)
  --upload-certs                         上传 control-plane 证书到 kubeadm-certs Secret.

安装网络插件

网络插件有flannel、calico、canal 和 weave,根据自己的需求选择。
1、安装flannel

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

2、安装calico

curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/calico.yaml -O 	
kubectl apply -f calico.yaml

工作节点添加

1、安装完成网络插件后master节点显示Ready状态

root@master:~# kubectl get nodes
NAME     STATUS   ROLES           AGE     VERSION
master   Ready    control-plane   3d18h   v1.26.3

2、添加工作节点
将节点加入集群,在初始化Master节点会生成kubeadm join命令,要使用主节点初始化过程中记录的kubeadm join命令

kubeadm join 11.0.1.131:6443 --token znxygv.852vaiqg9ldsq4vn   --discovery-token-ca-cert-hash sha256:995f8cd06cd503ce5e365852781de0911b63d88cb50ae04b6ccc7df070246748

3、验证节点添加结果
最终状态为3个节点状态为Ready,所有Pod状态为Running。

root@master:~# kubectl get nodes
NAME     STATUS   ROLES           AGE     VERSION
master   Ready    control-plane   3d18h   v1.26.3
node01   Ready    <none>          3d14h   v1.26.3
node02   Ready    <none>          3d14h   v1.26.3
	
root@master:~# kubectl get pod -A
NAMESPACE     NAME                                               READY   STATUS    RESTARTS        AGE
kube-system   calico-kube-controllers-79bfdd4898-j5r2v           1/1     Running   3 (2d21h ago)   3d13h
kube-system   calico-node-p4b96                                  1/1     Running   1 (3d ago)      3d13h
kube-system   calico-node-tx9tx                                  1/1     Running   1 (3d ago)      3d13h
kube-system   calico-node-w479t                                  1/1     Running   0               3d13h
kube-system   coredns-567c556887-55wl2                           1/1     Running   1 (3d ago)      3d18h
kube-system   coredns-567c556887-9dgds                           1/1     Running   1 (3d ago)      3d18h
kube-system   etcd-master                                        1/1     Running   1 (3d ago)      3d18h
kube-system   kube-apiserver-master                              1/1     Running   1 (3d ago)      3d18h
kube-system   kube-controller-manager-master                     1/1     Running   4 (13h ago)     3d18h
kube-system   kube-proxy-9c4qf                                   1/1     Running   1 (3d ago)      3d14h
kube-system   kube-proxy-dfp6p                                   1/1     Running   1 (3d ago)      3d14h
kube-system   kube-proxy-plq9r                                   1/1     Running   1 (3d ago)      3d18h
kube-system   kube-scheduler-master                              1/1     Running   5 (13h ago)     3d18h
myserver      myserver-nginx-deployment-596d5d9799-hrfsv         1/1     Running   0               2d23h
myserver      myserver-tomcat-app1-deployment-6bb596979f-n29nq   1/1     Running   0               2d23h

部署nginx工作负载验证集群可用性

1、通过yaml文件声明式部署工作负载。

kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: myserver-nginx-deployment-label
  name: myserver-nginx-deployment
  namespace: myserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myserver-nginx-selector
  template:
    metadata:
      labels:
        app: myserver-nginx-selector
    spec:
      containers:
      - name: myserver-nginx-container
        image: nginx
        #command: ["/apps/tomcat/bin/run_tomcat.sh"]
        #imagePullPolicy: IfNotPresent
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
#        resources:
#          limits:
#            cpu: 2
#            memory: 2Gi
#          requests:
#            cpu: 500m
#            memory: 1Gi	
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: myserver-nginx-service-label
  name: myserver-nginx-service
  namespace: myserver
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30004
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30443
  selector:
    app: myserver-nginx-selector

# kubectl apply -f nginx.yaml
# kubectl get pod -n myserver
NAME                                               READY   STATUS    RESTARTS   AGE
myserver-nginx-deployment-596d5d9799-hrfsv         1/1     Running   0          2d23h
root@master:~# kubectl get svc -n myserver
NAME                           TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
myserver-nginx-service         NodePort   10.200.211.39    <none>        80:30004/TCP,443:30443/TCP   3d12h

3、通过集群节点IP访问nginx

;