Kubernetes_架构_Init启动日志和Join日志、核心组件

一、前言

本文主要介绍k8s架构,包括 k8s启动、系统组件 .

二、k8s启动

2.1 Master和Node功能分工

官网 :https://kubernetes.io/zh/docs/concepts/architecture/master-node-

Master:Master是K8S集群中的控制节点,负责整个集群的管理和控制,可以做成高可用,防止一台Master打竞技或者不可用。Master上运行着一些关键的组件:比如API Server,Controller Manager,Scheduler等

Node:Node会被Master分配一些工作负载,当某个Node不可用时,会将工作负载转移到其他Node节点上。 Node上有一些关键的进程:kubelet,kube-proxy,docker container

查看集群中的Node

# 查看集群中的Node列表
kubectl get nodes 
# 查看集群中的每个Node占用的cpu和内存
kubectl top nodes 
# 查看集群中的单个Node详细信息
kubectl describe node node-name

小结:一般来说,程序员自己 通过 yaml 新建的 pod,会自动分配到 worker-node 节点上,不会被随机分配到 master 节点上,底层原因是因为使用 kubeadm 安装的k8s集群,master上会有一个污点。

2.2 master节点上执行 kubeadm init 日志分析

kubeadm init 和 kubeadm join 的时候,打印出了很多日志,这些日志 kubernetes 源码中打印出来( github 可以下载kubernetes源码),安装的时候,看懂这些启动日志是已经比较有趣的事情,也可以让自己做到心中有数。先看 kubeadm init 的日志。

master节点执行 kubeadm init 之后,内部执行了九个步骤。

第一步,检查preflight

第一步,检查preflight:进行一系列检查[init之前的检查],以确定这台机器可以部署

对应的日志如下:

在这里插入图片描述

[init] Using Kubernetes version: v1.14.0 # 使用k8s版本 1.14
[preflight] Running pre-flight checks   # 运行预先检查
[preflight] Pulling images required for setting up a Kubernetes cluster  # 拉取镜像(一个k8s集群所需要的)
# 这可能会花费一定时间,取决于你的网络速度
[preflight] This might take a minute or two, depending on the speed of your internet connection
# 你也可以使用 'kubeadm config images pull' 命令事先执行这个操作。
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'

You can also perform this action in beforehand using ‘kubeadm config images pull’
你也可以使用 ‘kubeadm config images pull’ 命令事先执行这个操作。这个命令会下载和提前准备所有需要的 Kubernetes 组件镜像,以避免在创建集群时因为网络问题而导致的下载失败。这个命令可以在执行 ‘kubeadm init’ 之前或者作为 ‘kubeadm init’ 的参数来执行。执行 ‘kubeadm config images pull’ 命令需要使用正确的镜像仓库地址和版本号。在执行命令之前,你需要确保有足够的磁盘空间和网络带宽。

第二步,生成一系列证书

第二步,生成 /etc/kubernetes/pki/ 目录下一系列证书:生成kubernetes对外提供服务所需要的各种证书可对应目录,也就是生成私钥和数字证书 /etc/kubernetes/pki/*

在这里插入图片描述

[certs] Using certificateDir folder "/etc/kubernetes/pki"  #使用证书目录 /etc/kubernetes/pki
# (在/etc/kubernetes/pki目录下)生成ca证书和私钥(即ca.crt和ca.key)
[certs] Generating "ca" certificate and key 

# (在/etc/kubernetes/pki目录下)生成apsierver证书和私钥(即apsierver.crt和apsierver.key)
# apiserver证书被验证
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local w2] and IPs [10.96.0.1 192.168.100.152]

# (在/etc/kubernetes/pki目录下)生成apiserver-kubelet-client证书和私钥
# (在/etc/kubernetes/pki目录下)生成front-proxy-ca证书和私钥
# (在/etc/kubernetes/pki目录下)生成front-proxy-client证书和私钥
# (在/etc/kubernetes/pki目录下)生成apiserver-kubelet-client证书和私钥
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key

# (在/etc/kubernetes/pki目录下)生成 etcd/ca 证书和私钥
[certs] Generating "etcd/ca" certificate and key

# (在/etc/kubernetes/pki目录下)生成 etcd/server 证书和私钥
# etcd/server 证书被签名
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost w2] and IPs [192.168.100.152 127.0.0.1 ::1]


# (在/etc/kubernetes/pki目录下)生成 etcd/peer 证书和私钥
# etcd/peer 证书被签名
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost w2] and IPs [192.168.100.152 127.0.0.1 ::1]

# (在/etc/kubernetes/pki目录下)生成 etcd/healthcheck-client 证书和私钥
# (在/etc/kubernetes/pki目录下)生成 apiserver-etcd-client 证书和私钥
# (在/etc/kubernetes/pki目录下)生成 sa 私钥和公钥(即sa.key sa.pub)
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key

在这里插入图片描述

第三步:生成一系列kubeconfig文件

第三步:生成 /etc/kubernetes/ 目录下,一系列为其他组件访问kube-ApiServer所需的配置文件xxx.conf

ls /etc/kubernetes/ 
admin.conf controller-manager.conf kubelet.conf scheduler.conf

在这里插入图片描述
在这里插入图片描述

# 使用/操作 /etc/kubernetes 目录下的kubeconfig
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"

# 写/生成 /etc/kubernetes 目录下的admin.conf  (复制到/root/.kube/config,kubectl命令工具连接apiserver )
# 写/生成 /etc/kubernetes 目录下的kubelet.conf  (kubelet组件连接apiserver )
# 写/生成 /etc/kubernetes 目录下的controller-manager.conf  (controller-manager组件连接apiserver )
# 写/生成 /etc/kubernetes 目录下的scheduler.conf  (scheduler组件连接apiserver )
[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

对于 /etc/kubernetes/ 目录下的四个文件,其作用是:

admin.conf kubectl 访问 apiServer 的 kubeconfig 文件 (cp admin.conf /root/.kube/config 后,kubectl就可以访问apiserver了)
kubelet.conf kubelet 访问 apiServer 的 kubeconfig 文件
controller-manager.conf controllerManager 访问 apiServer 的 kubeconfig 文件
scheduler.conf scheduler 访问 apiServer 的 kubeconfig 文件

这四个文件都是 kubeconfig ,格式都是 user (即client,包括key和crt) 和 cluster 构成,然后通过 user 和 cluster 构成 context.

先看一下 admin.conf kubeconfig文件是如何实现 kubectl 访问 apiserver 集群的,如下:

(1) 有了$HOME/.kube/config就可以使用kubectl和K8s集群打交道了,这个文件是来自于 /etc/kubernetes/admin.conf,就是将 /etc/kubernetes/admin.conf 这个拷贝到 $HOME/.kube/config ,如下:

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

(2)kubeconfig中包含了cluster、user和context信息:kubectl config view

(3)允许kubectl快速切换context,管理多集群

在这里插入图片描述

除了 admin.conf ,其他三个都是直接给 kubelet 和 两个静态Pod使用的(静态Pod一共四个:还有一个静态Pod就是 APIServer 自己,最后一个静态Pod是 etcd ,etcd根本不访问 apiserver,只有 apiserver 访问 etcd,所以 etcd 不需要 kubeconfig 证书),通过静态 Pod 通过文件映射的方式读入 Pod。

按顺序来,先看 kubelet ,它本质是一个linux服务,是使用linux服务启动的,不是 Pod 的方式启动的,所有没有 yaml 文件可以查看,但是 kubelet 启动的时候使用 kubelet-bootstrap.conf 访问 apiserver, kubelet 运行的时候使用 kubelet.conf 访问 apiserver.
还有 kubelet 与 apiserver 相互访问的证书在 /var/lib/kubelet/pki 目录下还有一份,对于 kubelet-client-current.pem 其实和 /etc/kubernetes/kubelet.conf 其实是一样的,详细请查看 kubelet服务全解析

再看 kube-controller-manager ,看一下它的 yaml 里面是如何将宿主机的kubeconfig映射到Pod里面的,如下:

kubectl get pod kube-controller-manager-m -o yaml -n kube-system
    - mountPath: /etc/kubernetes/controller-manager.conf
      name: kubeconfig
      readOnly: true   # 这个文件对于Pod来说,是只读的
  - hostPath:
      path: /etc/kubernetes/controller-manager.conf   # 宿主机路径
      type: FileOrCreate
    name: kubeconfig

最后看 kube-scheduler,看一下它的 yaml 里面是如何将宿主机的kubeconfig映射到Pod里面的,如下:

kubectl get pod kube-scheduler-m -o yaml -n kube-system
    volumeMounts:
    - mountPath: /etc/kubernetes/scheduler.conf
      name: kubeconfig
      readOnly: true    # 这个文件对于Pod来说,是只读的
  volumes:
  - hostPath:
      path: /etc/kubernetes/scheduler.conf  # 宿主机路径
      type: FileOrCreate
    name: kubeconfig

最后说一下etcd,它也属于四个静态Pod之一,但是它不访问apiserver,所以它不需要 kubeconfig 证书。但是 apiserver 访问它,所有它需要自己作为服务端的证书,在/etc/kubernetes/pki/etcd;而且 configmap 和 secret 都存储在 etcd 里面,这些数据需要持久化,使用目录 /var/lib/etcd 。

kubectl get pod etcd-m -o yaml -n kube-system
    volumeMounts:
    - mountPath: /var/lib/etcd   # 数据持久化
      name: etcd-data
    - mountPath: /etc/kubernetes/pki/etcd   # 证书
      name: etcd-certs
  volumes:
  - hostPath:
      path: /etc/kubernetes/pki/etcd
      type: DirectoryOrCreate
    name: etcd-certs
  - hostPath:
      path: /var/lib/etcd
      type: DirectoryOrCreate
    name: etcd-data

k8s 控制器管理Pod四种方式:
无状态的deployment(不存储数据) + 有头service [因为不存储数据,所以不需要持久化]
有状态的statefulset(存储数据) + 无头service(headless service) + pv/pvc (pod - hostPath 或者 pod - nfs 或者 pod - pvc - pv -nfs ) [因为存储数据,所以需要持久化]
daemonset 两个特点:Pod在每个Node上部署一个,每个Pod都是使用宿主机IP
job/cronjob 保证Pod运行一次性任务或定时任务

问题1:ds 如何实现使用宿主机IP作为Pod IP?
回答:通过设置 hostNetwork: true 属性来保证直接使用宿主机的 ip ,直接占用宿主机的 port ,而不是使用 calico 生成的ip (其实四个静态Pod也都是通过这样让Pod使用宿主机的IP)

问题2:ds 如何实现每个 Node 上存放一个Pod?
回答:通过在 yaml 中使用 nodeSelector: beta.kubernetes.io/os: linux 来保证只有那些具有kubernetes.io/os=linux标签的节点才会运行Pod,但是默认情况下 kubeadm init 安装的 k8s 集群,每个 node 上都会有这个标签,所以实现了每个Node上一个Pod,所以 ds 没有/不需要 replicas 属性。

第四步:生成一系列启动yaml文件

第四步,生成 /etc/kubernetes/manifests 目录下一系列yaml文件:为master生成Pod配置文件,这些组件会被master节点上的kubelet读取到,并且创建对应资源

ls /etc/kubernetes/manifests/*.yaml 
etcd.yaml
kube-apiserver.yaml
kube-controller-manager.yaml 
kube-scheduler.yaml

这四个yaml启动文件,就是四个静态Pod

在这里插入图片描述
在这里插入图片描述

这些pod由kubelet直接管理,是静态pod,直接使用主机网络 kubelet读取manifests目录并管理各控制平台组件pod的启动与停止 要想修改这些pod,直接 vi xxx.yaml 修改manifests下的yaml文件, 然后 :wq 保存即可,看到 docker ps | grep apiserver/etcd/scheduler/manager 重新启动了就是生效了

问题:k8s中的静态Pod是什么意思?

静态Pod特点:
(1) 管理者:直接由Kubelet管理的Pod,由Kubelet在特定节点上创建和维护的,而不是由Kubernetes的控制平面(control-plane)管理。
(2) 启动yaml:静态Pod的启动 yaml 通常存储在节点上,Kubelet会定期检查这些启动 yaml,并在发现新的启动 yaml 时创建相应的Pod。一旦Pod被创建,Kubelet会负责其生命周期和健康状态的监控,以及在必要时重新启动。静态Pod只有四个,就是主节点 cd /etc/kubernetes/manifests/ 下面的四个 启动yaml 文件。
(3) Pod IP:Pod IP使用宿主机的 kubeadm init 命令中注册在 k8s 集群中的IP,所以这个 Pod 的 IP 是固定的,不会变的。(不是使用 CNI 插件生成的虚拟IP,这个固定IP 也和 Calico 固定IP技术没关系)

四个静态 Pod 都通过 hostNetwork: true 实现使用宿主机IP, 都通过 priorityClassName: system-node-critical 实现优点调度

cat /etc/kubernetes/manifests/etcd.yaml
  hostNetwork: true    # 使用宿主机IP作为Pod IP
  priorityClassName: system-node-critical   # Node资源不够时,优先保证这个Pod有资源使用,Evicted驱逐其他Pod
  
cat /etc/kubernetes/manifests/kube-apiserver.yaml
  hostNetwork: true    # 使用宿主机IP作为Pod IP
  priorityClassName: system-node-critical   # Node资源不够时,优先保证这个Pod有资源使用,Evicted驱逐其他Pod
  
cat /etc/kubernetes/manifests/kube-controller-manager.yaml
  hostNetwork: true    # 使用宿主机IP作为Pod IP
  priorityClassName: system-node-critical   # Node资源不够时,优先保证这个Pod有资源使用,Evicted驱逐其他Pod
  
cat /etc/kubernetes/manifests/kube-scheduler.yaml
  hostNetwork: true    # 使用宿主机IP作为Pod IP
  priorityClassName: system-node-critical   # Node资源不够时,优先保证这个Pod有资源使用,Evicted驱逐其他Pod

第五步,下载镜像

05-下载镜像

下载镜像,等待控制平面启动,k8s.gcr.io下载不了,所以我们先提前下载并且tag好了

(1) 创建kubeadm.sh脚本,用于拉取镜像/打tag/删除原有镜像

#!/bin/bash

set -e

KUBE_VERSION=v1.21.0
KUBE_PAUSE_VERSION=3.4.1
ETCD_VERSION=3.4.13-0
CORE_DNS_VERSION=v1.8.0

GCR_URL=k8s.gcr.io
ALIYUN_URL=registry.cn-beijing.aliyuncs.com/dadfdafsd

images=(kube-proxy:${KUBE_VERSION}
kube-scheduler:${KUBE_VERSION}
kube-controller-manager:${KUBE_VERSION}
kube-apiserver:${KUBE_VERSION}
pause:${KUBE_PAUSE_VERSION}
etcd:${ETCD_VERSION}
coredns:${CORE_DNS_VERSION})

for imageName in ${images[@]} ; do
  docker pull $ALIYUN_URL/$imageName
  docker tag  $ALIYUN_URL/$imageName $GCR_URL/$imageName
  docker rmi $ALIYUN_URL/$imageName
done

(2) 运行脚本和查看镜像

# 运行脚本
sh ./kubeadm.sh

# 查看镜像
docker images

最后执行

docker tag k8s.gcr.io/coredns:v1.8.0 k8s.gcr.io/coredns/coredns:v1.8.0

执行 kubeadm inti 之前先执行这个,这样就有镜像了,kubeadm init 直接拿来用,不用去 docker pull ,因为国内网络不通。

第六步,启动kubelet和四个静态Pod

06-启动各个组件,包括 kubelet 和 /etc/kubernetes/manifests/目录下的静态Pod

一旦这些 YAML 文件出现在被 kubelet 监视的/etc/kubernetes/manifests/目录下,kubelet就会自动创建这些yaml文件定义的pod,即master组件的容器。master容器启动后,kubeadm会通过检查localhost: 6443/healthz这个master组件的健康状态检查URL,等待master组件完全运行起来

如下:
在这里插入图片描述

# [kubelet启动]写kubelet环境变量到 /var/lib/kubelet/kubeadm-flags.env 文件
# [kubelet启动]写kubelet配置项到 /var/lib/kubelet/config.yaml 文件
# [kubelet启动]启动kubelet
[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

# [控制面板]使用/操作目录 /etc/kubernetes/manifests
# [控制面板]创建静态Pod kube-apiserver
# [控制面板]创建静态Pod kube-controller-manager
# [控制面板]创建静态Pod kube-scheduler
[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"

# [分布式数据中心]创建静态Pod etcd
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"

Etcd英文全称是分布式键值对存储,是存放configmap和secret的
The full English name of etcd in k8s is “etcd distributed key-value store”. In Kubernetes, etcd is used as a distributed datastore to store and manage the configurations and states of the Kubernetes cluster.

第七步,安装默认插件(kube-proxy & coredns)

07-安装默认插件,kubernetes默认kube-proxy和DNS两个插件是必须安装的,dns插件安装了会出于pending状态,要等网络插件安装完成,比如calico

第八步,存储配置到ConfigMap & 给主节点打上标签和污点

08-将ca.crt等 Master节点的重要信息,通过ConfigMap的方式保存在etcd中,供后续部署node节点使用;给主节点打上标签和污点

# [等待控制面板]等待kubelet启动静态目录 /etc/kubernetes/manifests 下的yaml,构成控制面板,大概花费4分钟
# [kubelet检查]初始化40s过去了
# [api客户端]在xxx秒钟后,所有的控制面板组件都是健康的 (因为四个静态Pod里面都有探针,健康与否是探针通过调接口来确定)

[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
[kubelet-check] Initial timeout of 40s passed.
[apiclient] All control plane components are healthy after 98.503317 seconds

# [更新配置]使用kube-system命名空间里面的configmap kubeadm-config来存储配置
# 在kube-system命名空间里面创建configmap kubelet-config-1.21,用于整个集群
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.21" in namespace kube-system with the configuration for the kubelets in the cluster

# 跳过更新证书
[upload-certs] Skipping phase. Please see --upload-certs
# 给主节点添加标签Label
# 给主节点添加污点Taints
[mark-control-plane] Marking the node m as control-plane by adding the labels: [node-role.kubernetes.io/master(deprecated) node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node m as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]

先看一下两个configmap kubeadm-config 和 kubelet-config-1.21 ,一个是kubeadm 的configmap,一个是kubelet 的configmap

[root@localhost ~]# kubectl get configmap -A
NAMESPACE         NAME                                 DATA   AGE
default           kube-root-ca.crt                     1      19m
kube-node-lease   kube-root-ca.crt                     1      19m
kube-public       cluster-info                         2      20m
kube-public       kube-root-ca.crt                     1      19m
kube-system       calico-config                        4      10m
kube-system       coredns                              1      20m
kube-system       extension-apiserver-authentication   6      20m
kube-system       kube-proxy                           2      20m
kube-system       kube-root-ca.crt                     1      19m
kube-system       kubeadm-config                       2      20m  # kubeadm-config
kube-system       kubelet-config-1.21                  1      20m  # kubelet-config

先看 kubeadm 的 configmap ,如下:

[root@localhost ~]# kubectl get configmap kubeadm-config -o yaml -n kube-system
apiVersion: v1
data:
  ClusterConfiguration: | # kubeadm安装中,集群配置(APIServer DNS Etcd network网段)
    apiServer:
      extraArgs:
        authorization-mode: Node,RBAC
      timeoutForControlPlane: 4m0s
    apiVersion: kubeadm.k8s.io/v1beta2
    certificatesDir: /etc/kubernetes/pki  # kubeadm证书目录
    clusterName: kubernetes  # 集群名
    controllerManager: {}
    dns:    # dns
      type: CoreDNS
    etcd:   # etcd用来保存configmap和secret,需要数据目录
      local:
        dataDir: /var/lib/etcd
    imageRepository: k8s.gcr.io   # kubeadm安装的时候使用的静态仓库(所以拉下来的镜像要改成这个域名前缀,否则kubeadm无法使用)
    kind: ClusterConfiguration
    kubernetesVersion: v1.21.0    # k8s 版本
    networking:                   # network网段,包括dns域名、pod子网、svc子网
      dnsDomain: cluster.local
      podSubnet: 10.244.0.0/16
      serviceSubnet: 10.96.0.0/12
    scheduler: {}
  ClusterStatus: |  # kubeadm安装中,集群状态
    apiEndpoints:
      m:
        advertiseAddress: 192.168.100.151
        bindPort: 6443
    apiVersion: kubeadm.k8s.io/v1beta2
    kind: ClusterStatus
kind: ConfigMap
metadata:
  creationTimestamp: "2023-06-18T13:12:34Z"
  name: kubeadm-config
  namespace: kube-system
  resourceVersion: "211"
  uid: 8cfb13e7-4b65-4a3d-bcd2-b2c6be79ea76

再看这个configmap 是kubelet的config配置,kubelet包括启动参数文件和其他四个文件,还可以自定义kubelet并启动,这个文件所有参数都在kubelet 专属文章中讲解 kubelet服务全解析

[root@localhost ~]# kubectl get configmap kubelet-config-1.21 -o yaml -n kube-system
apiVersion: v1
data:
  kubelet: |
    apiVersion: kubelet.config.k8s.io/v1beta1
    authentication:
      anonymous:
        enabled: false
      webhook:
        cacheTTL: 0s
        enabled: true
      x509:
        clientCAFile: /etc/kubernetes/pki/ca.crt
    authorization:
      mode: Webhook
      webhook:
        cacheAuthorizedTTL: 0s
        cacheUnauthorizedTTL: 0s
    cgroupDriver: systemd
    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
    kind: KubeletConfiguration
    logging: {}
    nodeStatusReportFrequency: 0s
    nodeStatusUpdateFrequency: 0s
    rotateCertificates: true
    runtimeRequestTimeout: 0s
    shutdownGracePeriod: 0s
    shutdownGracePeriodCriticalPods: 0s
    staticPodPath: /etc/kubernetes/manifests
    streamingConnectionIdleTimeout: 0s
    syncFrequency: 0s
    volumeStatsAggPeriod: 0s
kind: ConfigMap
metadata:
  annotations:
    kubeadm.kubernetes.io/component-config.hash: sha256:8912bdfe80280dffc9e637149eb28ce3727d3d140cb1e7d43174177989e59620
  creationTimestamp: "2023-06-18T13:12:34Z"
  name: kubelet-config-1.21
  namespace: kube-system
  resourceVersion: "214"
  uid: 3dbcce74-e4f3-45ef-8fe4-9526ea705c98

再看一下主节点上的标签Label和污点Taints

在这里插入图片描述

第九步,启动kube-proxy和coredns

09-设定当前node为master,master节点将不承担工作负载,为集群生成一个bootstrap token,包括token和sha256,如下

# [启动token]正在使用token xxx
# [启动token]正在配置启动token、集群信息配置项、rbac role
# [启动token]允许Node Bootstrap tokens获取节点列表:这允许Node Bootstrap tokens在启动时获取Kubernetes集群中的节点列表,以便进行正确的授权和访问。
# [启动token]允许Node Bootstrap tokens提交CSR:这允许Node Bootstrap tokens使用Certificate Signing Request(CSR)机制向Kubernetes集群提交证书请求。
# [启动token]允许csrapprover自动批准CSR:这允许集群中的csrapprover controller自动批准通过Node Bootstrap tokens提交的CSR请求。
# [启动token]允许节点客户端证书轮换:这允许节点使用的所有客户端证书在集群中进行定期轮换,以确保证书在时间上不会过期。
# [启动token]正常创建名为 cluster-info 的配置项,在 kube-public 命名空间
[bootstrap-token] Using token: frii81.buyukgqjtvb4k7jr
[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启动完成]更新 /etc/kubernetes/kubelet.conf 文件中的客户端证书和密钥
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key


# 应用coredns、应用kube-proxy (除kubelet和四个静态Pod之外,两个网络插件,再加上calico就是三个网络插件了)
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

在Kubernetes集群中启用Node Bootstrap tokens的相关配置和RBAC规则。Node Bootstrap token是在Kubernetes集群中启动节点时使用的一种临时身份验证方式,它们具有一个短期有效性和受限的访问权限。

上述配置和RBAC规则的作用如下:

(1) 允许Node Bootstrap tokens获取节点列表:这允许Node Bootstrap tokens在启动时获取Kubernetes集群中的节点列表,以便进行正确的授权和访问。
(2) 允许Node Bootstrap tokens提交CSR:这允许Node Bootstrap tokens使用Certificate Signing Request(CSR)机制向Kubernetes集群提交证书请求。
(3) 允许csrapprover自动批准CSR:这允许集群中的csrapprover controller自动批准通过Node Bootstrap tokens提交的CSR请求。
(4) 允许节点客户端证书轮换:这允许节点使用的所有客户端证书在集群中进行定期轮换,以确保证书在时间上不会过期。

通过配置和启用这些功能和RBAC规则,Kubernetes集群管理员可以更加安全地管理和控制节点访问和身份验证。

在这里插入图片描述

最后,集群成功日志,如下:

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/

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

kubeadm join 192.168.100.151:6443 --token frii81.buyukgqjtvb4k7jr \
	--discovery-token-ca-cert-hash sha256:47c9d897996b9aa95fc525b830663f0a4d3110b312316d6089141dc65a827f87 

在这里插入图片描述

在这里插入图片描述

2.3 kubeadm join

kubeadm join 192.168.0.51:6443 --token yu1ak0.2dcecvmpozsy8loh \ --discovery-token-ca-cert-hash
sha256:5c4a69b3bb05b81b675db5559b0e4d7972f1d0a61195f217161522f464c307b0

kubeadm join 三个变量 = masterIp + token + hash(即sha256)

01 join前检查

02 discovery-token-ca-cert-hash用于验证master身份

# 可以计算出来,在w节点上执行
  openssl x509 -in /etc/kubernetes/pki/ca.crt -noout -pubkey | openssl rsa -pubin - outform DER 2>/dev/null | sha256sum | cut -d' ' -f1 
  # 最终hash的值
   909adc03d6e4bd676cfc4e04b864530dd19927d8ed9d84e224101ef38ed0bb96

03 token用于master验证node

# 在master上节点上,可以查看对应的token 
kubectl get secret -n kube-system | grep bootstrap-token 
# 得到token的值 
kubectl get secret/bootstrap-token-kggzhc -n kube-system -o yaml 
# 对token的值进行解码 
echo NHRzZHp0Y2RidDRmd2U5dw==|base64 -d --->4tsdztcdbt4fwe9w 
# 最终token的值 
kggzhc.4tsdztcdbt4fwe9w 

实在忘了怎么办?
https://gper.club/articles/7e7e7f7ff7g5bgc0g68

三、k8s集群核心组件

支撑一个k8s集群运行起来的核心组件汇总,如下图:

在这里插入图片描述

  • kubeadm 安装工具,仅仅只是kubernetes的安装工具,安装完之后就没什么用了
  • kubectl 是客户端,任何一个机器有了 kubectl 和 .kube/config 就可以任意操作 k8s-cluster
  • apiServer是中枢纽带,包括两个知识点:k8s所有接口/证书,一个外部请求 Request 在 k8s 中的处理流程
  • etcd 整个集群的配置中心,所有集群的系统配置、系统状态都存储在etcd
  • scheduler是调度策略,就是决定哪个pod需要随机放到哪个node上
  • controller Manager 用来管理不同的 Controller 控制器,控制器是管理 Pod 的,包括 RS Deployment StatefulSet DaemonSet Job/CronJob
  • kubelet 本质是一个Linux服务,运行在所有节点中(包括master和node),用来管理所有的 node ,将所在节点的Pod的信息汇报给apiServer (kubelet和apiserver可以相互访问)
  • kube-proxy 以 Pod 的形式运行,控制器是 DaemonSet ,所有节点都运行,用于将 service 收到的流量负载均衡到控制器下面的Pod,使用 netstat -ntlp | grep kube-proxy 可以看到 service 暴露在宿主机是端口都是 kube-proxy 进程;kube-proxy 主要两种模式 iptables/ipvs ,底层都是 linux iptables 规则。
  • dns将域名解析为ip,包括外网域名(如 www.baidu.com) 和 serviceName.ns
  • cni插件用来实现Pod之间数据通信,分为同一个Node上的Pod,不同Node上的Pod,Calico还有固定IP和网络策略NetworkPolicy两个额外功能
  • dashboard只是控制面板,但是这个比较简陋,GitHub 上有一个 Kube-board 做的好一点,两个都是 Pod 运行起来

在这里插入图片描述

Kubernetes是Go语言写的,源码地址 :https://github.com/kubernetes/kubernetes
https://github.com/kubernetes/kubernetes/tree/release-1.14

01 kubectl

kubectl 本质是一个操作集群的客户端,也就是和集群打交道。所以它并不是集群的核心组件,集群中没有它也可以正常运行。

语法 :kubectl [command] [TYPE] [NAME] [flag]
官网 :https://kubernetes.io/docs/reference/kubectl/overview/

command: 动词,用于操作k8s集资源对象的命令,比如apply、delete、describe、get等
TYPE: 类型,要操作资源对象的类型,区分大小写,比如pod[pods/po]、deployment
NAME: 具体名称,要操作对象的具体名称,若不指定,则返回该资源类型的全部对象[是默认命名空间下的]
flags: 可选

查看集群信息

# 查看集群的信息 
kubectl config view 
# 查看cluster的信息 
kubectl config get-clusters

创建资源,name可以是文件名,也可以是目录名

kubectl apply -f xxx.yaml
kubectl apply -f <directory> 

查看资源对象

# 查看Pod 
kubectl get pods 
# 查看Service 
kubectl get svc 

问题查看调试

# 启动日志调试
kubectl describe pod pod-name 
# 运行日志调试
kubectl logs -f pod-name 
# 进入容器调试
kubectl exec -it pod-name 
kubectl attach 

02 kube-apiserver

整个集群的中枢纽带,负责的事情很多

(1) /etc/kubernetes/manifests/kube-apiserver.yaml # kubelet管理的静态pod
(2) 认证:安全验证的一些文件
(4) 授权:–authorization-mode=Node,RBAC
(3) 准入控制:准入策略的拦截器
(5) --etcd # 配置apiserver访问etcd

03 kube-scheduler

单纯地调度pod,按照特定的调度算法和策略,将待调度Pod绑定到集群中某个适合的Node,并写入绑定信息,由对应节点的kubelet服务创建pod。

(1)/etc/kubernetes/manifests/kube-scheduler.yaml # kubelet管理的静态pod
(2)–address表示只在master节点上提供服务,不对外
(3)kubeconfig表示 yaml 通过文件映射方式传入 kube-scheduler,用户kube-scheduler 访问 apiserver

04 kube-controller-manager

负责集群中Node、Pod副本、服务的endpoint、命名空间、Service Account、资源配合等管理

会划分成不同类型的controller,每个controller都是一个死循环,在循环中controller通过apiserver监视自己控制资源的状态,一旦状态发生变化就会努力改变状态,直到变成期望状态

(1)/etc/kubernetes/manifests/kube-controller-manager.yaml # kubelet管理的静态pod
(2)参数设置ca-file
(3) 当有多个manager,是否需要进行leader选举

05 kubelet

集群中的所有节点都有运行,用于管理pod和container,每个kubelet会向apiserver注册本节点的信息,并向master节点上报本节点资源使用的情况

官网 :https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/

在k8s集群中,每个Node上都会启动一个kubelet服务进程,用于处理master节点下发到本节点的任务。管理Pod及Pod中的容器,每个kubelet进程会在API Server上注册节点自身信息,定期向Master节点汇报节点资源的使用情况,并通过cAdvisor监控容器和节点资源。

(1)kubelet由操作系统init[systemd]进行启动 ,不以Pod方式运行
(2)ls /lib/systemd/system/kubelet.service
(3)systemctl daemon-reload & systemctl restart kubelet

06 kube-proxy

集群中的所有节点都有运行,像service的操作都是由kube-proxy代理的,对于客户端是透明的

官网 :https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/

在k8s集群中,每个Node上都会运行一个kube-proxy进行,它是Service的透明代理兼负载均衡器,核心功能是将某个Service的访问请求转发到后端的多个Pod实例上。

serviceName.namespace 这样集群内的调用是需要 kube-proxy 底层来完成的,包括两种场景:
(1) 外部流量请求 Service ,通过 KubeProxy负载均衡到各个Pod
(2) 另一个Deployment的env中通过 serviceName.namespace 调用上一个Service,然后通过 kube-proxy 转到 Pod

无论那种情况,KubeProxy底层都是一条条 iptables 规则实现的

(1)kube-proxy由daemonset控制器实现在各个节点上都启动唯一实例
(2)配置项是 /var/lib/kube-proxy/config.conf(pod内) , kube-proxy不是静态pod
(3)kubectl get pods -n kube-system
(4)kubectl exec kube-proxy-jt9n4 -n kube-system – cat /var/lib/kube-proxy/config.conf
(5)mode:“” —># iptables

07 DNS

域名解析的问题

08 dashboard

需要有监控面板能够监测整个集群的状态

09 etcd

整个集群的配置中心,所有集群的状态数据,对象数据都存储在etcd中,configmap 和 secret 都存储在 etcd 中,etcd 的数据有通过挂盘的方式持久化到 master 所在机器,宿主机磁盘中。kubeadm引导启动的K8s集群,默认只启动一个etcd节点

(1) 启动文件:/etc/kubernetes/manifests/etcd.yaml # kubelet管理的静态pod
(2) 证书目录:etcd所使用的相关秘钥在/etc/kubernetes/pki/etcd里面
(3) 数据目录:etcd挂载master节点本地路径/var/lib/etcd用于运行时数据存储

四、尾声

本文介绍 kubeadm init 和 kubeadm join 日志分析,以及 k8s 集群核心组件,完成了。

对于 /etc/kubernetes/ 目录下的四个文件,其作用是:

admin.conf kubectl 访问 apiServer 的 kubeconfig 文件 (cp admin.conf /root/.kube/config 后,kubectl就可以访问apiserver了)
kubelet.conf kubelet 访问 apiServer 的 kubeconfig 文件
controller-manager.conf controllerManager 访问 apiServer 的 kubeconfig 文件
scheduler.conf scheduler 访问 apiServer 的 kubeconfig 文件

对于 /etc/kubernetes/manifests 目录下的四个yaml文件,启动就是四个静态Pod,四个静态Pod都通过 hostNetwork: true 实现使用宿主机IP, 都通过 priorityClassName: system-node-critical 实现优点调度

核心组件汇总:先是kubeadm和kubectl两个工具,一个是安装k8s集群,一个安装完之后操作k8s集群;再有就是四个静态Pod;然后是kubelet linux服务;再有是三个网络插件:kube-proxy负责给svc负载均衡到Pod,coredns域名域名解析(外网域名和 svc.ns),cni插件负责实现Pod之间通信;最后还有一个可视化面板 dashboard (第三方的kube-board)

四个静态Pod之间关系:apiserver 访问 etcd (使用x509证书),其他的 scheduler controller-manager 使用kubeconfig文件访问apiserver
kubelet 使用 kubelet.conf 访问 apiserver,apiserver 也可以使用 apiserver-kubelet-client.key/.crt 访问 kubelet
kubectl 使用 /root/.kube/config (由 /etc/kubernetes/admin.conf 复制过去) 访问 apiserver
三个网络插件:kube-proxy core-dns calico

在这里插入图片描述

天天打码,天天进步!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

祖母绿宝石

打赏一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值