1. 环境配置

(1)安装前环境配置

// 节点之间:主机名、MAC 地址、product_uuid 不能重复

$ hostname             // 查看主机名
#$ ip link
$ nmcli device show    // 查看 mac 地址
$ cat /sys/class/dmi/id/product_uuid       // 查看 product_uuid

一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。 Kubernetes 使用这些值来唯一确定集群中的节点。 如果这些值在每个节点上不唯一,可能会导致安装失败。

// 配置主机名解析

$ cat <<EOF >> /etc/hosts
192.168.10.224 c810224.xiodi.cn k8sinternal.xiodi.cn
192.168.10.214 c810214.xiodi.cn
EOF

// 配置 base和 epel 源

$ source <(curl -sL https://gitee.com/jack_zang/public-scripts/raw/master/shell/repo/centos8_use_aliyun_base_epel.sh)

关闭防火墙、selinux、swap,配置系统句柄数,修改内核参数,开启 ipvs,配置时间同步

$ source <(curl -sL https://gitee.com/jack_zang/kubernetes/raw/k8s-v1.26/install/kubeadm_1.26/prepare_env.sh)

注意:请自行配置主机名,已经dns解析主机名

(2)升级内核(可不升级)

$ source <(curl -sL https://gitee.com/jack_zang/kubernetes/raw/k8s-v1.26/install/kubeadm_1.26/prepare_env_update_kernel.sh)

$ reboot
$ uname -r
6.0.0-1.el8.elrepo.x86_64

(3)安装 kubernetes

$ source <(curl -sL https://gitee.com/jack_zang/kubernetes/raw/k8s-v1.26/install/kubeadm_1.26/kubernetes_install.sh)

主要安装4个软件:

  • containerd:容器运行时
  • kubeadm:用来初始化集群的指令
  • kubelet:在集群中的每个节点上用来启动 Pod 和容器等。
  • kubectl:用来与集群通信的命令行工具(kubernetes 集群客户端)。

2. kubeadm 配置单 master 集群

(1)master 节点初始化集群

// 生成默认配置,也可不生成,直接使用下面的配置

$ kubeadm config print init-defaults --component-configs KubeletConfiguration > /etc/kubernetes/kubeadm-config.yaml

如果不指定任何组件,默认只有 InitConfiguration 和 ClusterConfiguration 配置,支持的组件有:
KubeProxyConfiguration 和 KubeletConfiguration 。

// kubeadm 配置文件

$ vi /etc/kubernetes/kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
imageRepository: registry.aliyuncs.com/google_containers
kubernetesVersion: 1.26.0
controlPlaneEndpoint: "k8sinternal.xiodi.cn:6443"
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
  podSubnet: 10.244.0.0/16
apiServer:
  timeoutForControlPlane: 4m0s
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
scheduler: {}
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 0s
    cacheUnauthorizedTTL: 0s
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
cpuManagerReconcilePeriod: 0s
evictionPressureTransitionPeriod: 0s
fileCheckFrequency: 0s
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 0s
imageMinimumGCAge: 0s
logging:
  flushFrequency: 0
  options:
    json:
      infoBufferSize: "0"
  verbosity: 0
memorySwap: {}
nodeStatusReportFrequency: 0s
nodeStatusUpdateFrequency: 0s
rotateCertificates: true
runtimeRequestTimeout: 0s
shutdownGracePeriod: 0s
shutdownGracePeriodCriticalPods: 0s
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 0s
syncFrequency: 0s
volumeStatsAggPeriod: 0s
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs

基本上和默认值一样,主要注意以下几个地方:

imageRepository: registry.aliyuncs.com/google_containers
controlPlaneEndpoint: "k8sinternal.xiodi.cn:6443"   // 用作以后升级高可用使用
podSubnet: 10.244.0.0/16
cgroupDriver: systemd
mode: ipvs

如果计划将单个控制平面 kubeadm 集群升级成高可用, 你应该指定 --control-plane-endpoint 为所有控制平面节点设置共享端点。 端点可以是负载均衡器的 DNS 名称或 IP 地址。

除非另有说明,否则 kubeadm 使用与默认网关关联的网络接口来设置此控制平面节点 API server 的广播地址。 要使用其他网络接口,请为 kubeadm init 设置 --apiserver-advertise-address=<ip-address> 参数。 要部署使用 IPv6 地址的 Kubernetes 集群, 必须指定一个 IPv6 地址,例如 --apiserver-advertise-address=2001:db8::101

// 提前拉取镜像并初始化集群

$ kubeadm config images pull --config /etc/kubernetes/kubeadm-config.yaml
$ kubeadm init --config /etc/kubernetes/kubeadm-config.yaml
[init] Using Kubernetes version: v1.26.0
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [c810224.xiodi.cn k8sinternal.xiodi.cn kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.10.224]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [c810224.xiodi.cn localhost] and IPs [192.168.10.224 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [c810224.xiodi.cn localhost] and IPs [192.168.10.224 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 5.000994 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node c810224.xiodi.cn as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node c810224.xiodi.cn as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
[bootstrap-token] Using token: zfssa4.fu9qdw1crrxf9si7
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

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/

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:

  kubeadm join k8sinternal.xiodi.cn:6443 --token zfssa4.fu9qdw1crrxf9si7 \
    --discovery-token-ca-cert-hash sha256:dc8dadefc369872c395a5d5fe6ac20a71e15be7cce9a01a9fa542d0226111719 \
    --control-plane

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join k8sinternal.xiodi.cn:6443 --token zfssa4.fu9qdw1crrxf9si7 \
    --discovery-token-ca-cert-hash sha256:dc8dadefc369872c395a5d5fe6ac20a71e15be7cce9a01a9fa542d0226111719

// 配置用户认证证书

$ mkdir -p $HOME/.kube
$ cp -i /etc/kubernetes/admin.conf  $HOME/.kube/config
$ chown  $(id -u):$(id -g)  $HOME/.kube/config

kubeadm init 参数参考:https://kubernetes.io/zh-cn/docs/reference/setup-tools/kubeadm/
kubeadm init 带配置文件参考:https://kubernetes.io/zh-cn/docs/reference/setup-tools/kubeadm/kubeadm-init/#config-file

(2)安装 Helm

// 安装 helm

$ source <(curl -sL https://gitee.com/jack_zang/public-scripts/raw/master/shell/helm/helm-cmd-install.sh)

(3)安装网络组件 Calico

// 安装 pod network组件 Calico

$ curl -LO https://github.com/projectcalico/calico/releases/download/v3.25.0/tigera-operator-v3.25.0.tgz
$ helm show values tigera-operator-v3.25.0.tgz > calico-value.yaml  // 查看 chart 中可定义的配置

$ helm install calico tigera-operator-v3.25.0.tgz -n kube-system -f calico-value.yaml

// 验证 calico,重点是 tigera-operator,这个是 calico 操作管理容器

$ kubectl get pods -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
coredns-5bbd96d687-cmd94                   1/1     Running   0          93m
coredns-5bbd96d687-l2vjs                   1/1     Running   0          93m
etcd-c810224.xiodi.cn                      1/1     Running   0          94m
kube-apiserver-c810224.xiodi.cn            1/1     Running   0          94m
kube-controller-manager-c810224.xiodi.cn   1/1     Running   0          94m
kube-proxy-qv68f                           1/1     Running   0          93m
kube-scheduler-c810224.xiodi.cn            1/1     Running   0          94m
tigera-operator-54b47459dd-tntnx           1/1     Running   0          13m

// 验证 calico,查看 calico 安装

$ kubectl get pods -n calico-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-6b7b9c649d-k6667   1/1     Running   0          15m
calico-node-c9fzx                          1/1     Running   0          15m
calico-typha-7cf7b9cd86-tmmdl              1/1     Running   0          15m
csi-node-driver-2n62h                      2/2     Running   0          14m

// 查看 calico 向 k8s 添加的 api 资源

$ kubectl api-resources | grep calico
bgpconfigurations                              crd.projectcalico.org/v1               false        BGPConfiguration
bgppeers                                       crd.projectcalico.org/v1               false        BGPPeer
blockaffinities                                crd.projectcalico.org/v1               false        BlockAffinity
caliconodestatuses                             crd.projectcalico.org/v1               false        CalicoNodeStatus
clusterinformations                            crd.projectcalico.org/v1               false        ClusterInformation
felixconfigurations                            crd.projectcalico.org/v1               false        FelixConfiguration
globalnetworkpolicies                          crd.projectcalico.org/v1               false        GlobalNetworkPolicy
globalnetworksets                              crd.projectcalico.org/v1               false        GlobalNetworkSet
hostendpoints                                  crd.projectcalico.org/v1               false        HostEndpoint
ipamblocks                                     crd.projectcalico.org/v1               false        IPAMBlock
ipamconfigs                                    crd.projectcalico.org/v1               false        IPAMConfig
ipamhandles                                    crd.projectcalico.org/v1               false        IPAMHandle
ippools                                        crd.projectcalico.org/v1               false        IPPool
ipreservations                                 crd.projectcalico.org/v1               false        IPReservation
kubecontrollersconfigurations                  crd.projectcalico.org/v1               false        KubeControllersConfiguration
networkpolicies                                crd.projectcalico.org/v1               true         NetworkPolicy
networksets                                    crd.projectcalico.org/v1               true         NetworkSet

// 验证集群

$ kubectl get nodes
NAME               STATUS   ROLES           AGE    VERSION
c810224.xiodi.cn   Ready    control-plane   101m   v1.26.1

$ kubectl get pods -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
coredns-5bbd96d687-cmd94                   1/1     Running   0          101m
coredns-5bbd96d687-l2vjs                   1/1     Running   0          101m
etcd-c810224.xiodi.cn                      1/1     Running   0          101m
kube-apiserver-c810224.xiodi.cn            1/1     Running   0          101m
kube-controller-manager-c810224.xiodi.cn   1/1     Running   0          101m
kube-proxy-qv68f                           1/1     Running   0          101m
kube-scheduler-c810224.xiodi.cn            1/1     Running   0          101m
tigera-operator-54b47459dd-tntnx           1/1     Running   0          20m

(4)Node 节点加入集群

//加入集群

$ kubeadm join k8sinternal.xiodi.cn:6443 --token zfssa4.fu9qdw1crrxf9si7 --discovery-token-ca-cert-hash sha256:dc8dadefc369872c395a5d5fe6ac20a71e15be7cce9a01a9fa542d0226111719

//如果已经不记得加入集群的命令,创建一个新的 token,默认24小时后过期

$ kubeadm token create --print-join-command
kubeadm join k8sinternal.xiodi.cn:6443 --token 7llcyj.b9hc0xg8k2nnkxok --discovery-token-ca-cert-hash sha256:dc8dadefc369872c395a5d5fe6ac20a71e15be7cce9a01a9fa542d0226111719

// 验证节点

$ kubectl get pods -n kube-system -o wide
$ kubectl get nodes
NAME                  STATUS   ROLES           AGE    VERSION
c810214.xiodi.cn      Ready    <none>          13m    v1.26.1
c810224.xiodi.cn      Ready    control-plane   161m   v1.26.1

// 如果要加入 master 节点(先看看即可)

kubeadm join k8sinternal.xiodi.cn:6443 --token zfssa4.fu9qdw1crrxf9si7 --discovery-token-ca-cert-hash sha256:dc8dadefc369872c395a5d5fe6ac20a71e15be7cce9a01a9fa542d0226111719 --control-plane

3. 测试

// 创建 nginx deployment 和 svc

$ kubectl apply -f https://gitee.com/jack_zang/kubernetes/raw/k8s-v1.26/install/kubeadm_1.26/nginx-test.yaml

浏览器查看:http://NODEIP:32222

4. 扩展

(1)加入节点 token 详解

$ kubeadm token list        // 查看令牌
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
01rbno.71wjsyykart1q3ne   23h         2023-02-17T02:13:19Z   authentication,signing   <none>                                                     system:bootstrappers:kubeadm:default-node-token
...

$ kubeadm token create         // 创建令牌,默认情况下,有效性为 24 小时
ff4lq6.vez20elpkylwmipw

// 查看 `--discovery-token-ca-cert-hash` 的值
$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
6270d1e714a0c084619f2fc9e3560856253fb914d972259604862b9b4c593581

(2)删除节点

使用适当的凭证与控制平面节点通信,运行:

kubectl drain <node name> --delete-emptydir-data --force --ignore-daemonsets

在删除节点之前,请重置 kubeadm 安装的状态:

kubeadm reset

重置过程不会重置或清除 iptables 规则或 IPVS 表。如果你希望重置 iptables,则必须手动进行:

iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

如果要重置 IPVS 表,则必须运行以下命令:

ipvsadm -C

现在删除节点:

kubectl delete node <节点名称>

(3)清理控制平面

你可以在控制平面主机上使用 kubeadm reset 来触发尽力而为的清理。