Kubernetes工作节点的自动加入方法

2024/12/31 21:03:17

本文主要是介绍Kubernetes工作节点的自动加入方法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

数据中心的插图

当前的家庭实验室背景

对于一直关注我将一个功能齐全的 Kubernetes 集群带入生活,并在 illumos 中外部运行控制平面的那些人,现在终于可以拥有一个完全符合规范的集群了。

Cilium的v1.16版本终于可以通过BGP发布ClusterIP,实现了集成的可能性,这意味着外部控制平面可以通过由动态准入控制器提供的webhook进行连接,这些控制器实际上运行在数据平面,作为控制平面的扩展。

Cilium的下一个版本v1.17将带来一个备受期待的功能特性——一个无需kube-proxy的集群通过了CNCF Kubernetes认证测试(相关问题(#9207)最近已解决并合并到主分支)。这是一个好消息,因为它允许使用无侧car的Cilium服务网格构建一个100%符合标准的集群!

我直接并放弃了当前的 IPAM 预留并卸载了再重新安装了 Cilium 到 1.17.0-pre.0,使用了以下 helm 参数:

    # 声明 Apiserver IP 和端口  
    K8S_API_SERVER=  
    K8S_API_PORT=  
    # 需要填写具体的服务器IP和端口

航向值设置:

    cat << EOF > cilium-helm-values.yaml  
    用户提供的值:  
    bgpControlPlane:  
      enabled: true  
    bpf:  
      lbExternalClusterIP: true  
    cluster:  
      name: default-cluster  
    cluster.name: default-cluster  
    gatewayAPI:  
      enabled: true  
    hubble:  
      启用: true  
      metrics:  
        dashboards:  
          annotations:  
            grafana_folder: Cilium  
          启用: true  
          namespace: monitoring  
        enableOpenMetrics: true  
        启用:  
        - dns  
        - drop  
        - tcp  
        - icmp  
        - 流: 源上下文=工作负载名称|保留标识; 目标上下文=工作负载名称|保留标识  
        - kafka: 标签上下文=源命名空间,源工作负载,目标命名空间,目标工作负载,流量方向; 源上下文=工作负载名称|保留标识; 目标上下文=工作负载名称|保留标识  
        - httpV2: exemplars=true; 标签上下文=源IP, 源命名空间, 源工作负载, 目标IP, 目标命名空间, 目标工作负载, 流量方向; 源上下文=工作负载名称|保留标识; 目标上下文=工作负载名称|保留标识  
        serviceMonitor:  
          启用: true  
      operator:  
        prometheus:  
          启用: true  
          serviceMonitor:  
            启用: true  
      prometheus:  
        启用: true  
        serviceMonitor:  
          启用: true  
      relay:  
        启用: true  
        prometheus:  
          启用: true  
          serviceMonitor:  
            启用: true  
      ui:  
        启用: true  
    ingressController:  
      default: true  
      启用: true  
      负载均衡器模式: 专用  
    ipam:  
      模式: cluster-pool  
    k8sServiceHost: ${K8S_API_SERVER}  
    k8sServicePort: ${K8S_API_PORT}  
    kubeProxyReplacement: true  
    operator:  
      复本: 1  
    ciliumPods的滚动更新: true  
    EOF

同时,我终于能够升级到 Cilium BGP 控制平面 v2(https://docs.cilium.io/en/latest/network/bgp-control-plane/bgp-control-plane-v2/),这对我来说是一个特别兴奋的时刻。

BGP 控制平面 v2 的自定义资源定义在结构上有些许差异,但在基本结构上变化不大。组件被拆分成了 CiliumBGPClusterConfigCiliumBGPPeerConfigCiliumBGPAdvertisement。需要注意一下细节,CiliumLoadBalancerIPPool 的结构已从 .spec.cidr 更改为 .spec.blocks(为了增强灵活性)。

为了使用v2,需要创建以下文件。

    # 声明应通过BGP通告的CIDR地址段
    LB_CIDR=
    # 集群ASN
    CLUSTER_ASN=
    # 对等路由器的ASN和IP
    PEER_ASN=
    PEER_IP=

创建一个IP池设置

下面的命令将输出到 `cilium-ippool.yaml` 文件中,内容如下:

cat << "结束标记" > cilium-ippool.yaml
apiVersion: cilium.io/v2alpha1
kind: CiliumLoadBalancerIPPool
metadata:
name: ippool
spec:
blocks:

  • cidr: ${LB_CIDR}
    disabled: false
    结束标记

块定义了 CIDR 范围,其中 apiVersionkind 是特定于 Cilium 项目的术语。blocks 包含一个 CIDR 范围定义,disabled 表示是否禁用。

对于BGP,可以设置为如下所示的配置:
cat << EOF > cilium-bgp-v2.yaml  
---  
apiVersion: cilium.io/v2alpha1  
kind: CiliumBGPClusterConfig  
metadata:  
  name: cilium-bgp  
spec:  
  nodeSelector:  
    matchLabels:  
      bgp: worker  
  bgpInstances:  
  - name: "instance_asn"  
    localASN: ${CLUSTER_ASN}  
    peers:  
    - name: "peer_asn"  
      peerASN: ${PEER_ASN}  
      peerAddress: ${PEER_IP}  
      peerConfigRef:  
        name: "cilium-peer"  
---  
apiVersion: cilium.io/v2alpha1  
kind: CiliumBGPPeerConfig  
metadata:  
  name: cilium-peer  
spec:  
  transport:  
    peerPort: 179  
  families:  
    - afi: ipv4  
      safi: unicast  
      advertisements:  
        matchLabels:  
          advertise: "bgp"  
---  
apiVersion: cilium.io/v2alpha1  
kind: CiliumBGPAdvertisement  
metadata:  
  name: bgp-advertisements  
  labels:  
    advertise: 通告: bgp  
spec:  
  advertisements:  
    - advertisementType: "PodCIDR"  
      attributes:  
        communities:  
          standard: [ "65000:99" ]  
    - advertisementType: "Service"  
      service:  
        addresses:  
          - ClusterIP  
          - ExternalIP  
          - LoadBalancerIP  
      selector:             # <-- (选择所有服务)  
        matchExpressions:  
         - {key: somekey, operator: NotIn, values: ['never-used-value']}  
EOF
順便一提,這是在我的 Kubernetes 集群中運行的符合性測試結果,控制平面節點運行在 Illumos 上,而工作節點則運行在 Linux 上。挺厲害的,對不對?

运行了 7197 个规格中的 402 个测试,耗时约 6431.74 秒
成功啦!-- 402 通过 | 0 失败 | 6795 跳过了
通过了

Ginkgo 运行了 1 套测试套件,耗时约 1 小时 47 分 15 秒
测试套件通过了

# 基于证书的机构

# 基于证书的机构

# 证书机构

因为我之前已经详细写过配置CA的过程,我不会再重复那些步骤。相反,我将介绍让CFSSL Api运行起来所需的步骤。

虽然以下步骤是针对illumos描述的,但对于Linux(或BSD)系统来说,也会采取类似的步骤,只是使用不同的服务清单。

可以使用各种方式(如下所述 <https://kubernetes.io/docs/tasks/administer-cluster/certificates/> )让证书颁发机构运行起来,但我们会专注于 kubeadm 选择的那个方式(它支持带有 `-serve` 标志的 API)。

API 需要一个后端支持,你可以选择使用鹅(goose)项目(<https://github.com/cloudflare/cfssl/tree/master/certdb>),或者参考这篇博客文章<https://bouchaud.org/blog/en/posts/initializing-root-intermediate-ca-with-cfssl/>。

以下步骤会修改对CA的一些先前配置。

首先,让我们声明一些关键的变量。
# 创建一个用于与CA进行身份验证的密钥
AUTH_KEY=$(openssl rand -hex 16) 生成一个16位的随机密钥
# 运行CFSSL API的主机的IP
CA_URL
* 创建一个 SQLite 后端吧
cat << EOF > sqlite.sql  
创建表 证书 (  
  序列号            blob NOT NULL,  
  权威密钥标识符 blob NOT NULL,  
  ca_label                 blob,  
  状态                   blob NOT NULL,  
  撤销原因               int,  
  过期                   timestamp,  
  撤销时间               timestamp,  
  发行时间               timestamp,  
  生效时间               timestamp,  
  元数据                 blob,  
  sans                     blob,  
  通用名称              blob,  
  pem                      blob NOT NULL,  
  主键(序列号, 权威密钥标识符)  
);  

创建表 ocsp响应 (  
  序列号            blob NOT NULL,  
  权威密钥标识符 blob NOT NULL,  
  正文              blob NOT NULL,  
  过期              timestamp,  
  主键(序列号, 权威密钥标识符),  
  外键(序列号, 权威密钥标识符) 引用 证书(序列号, 权威密钥标识符)  
);  
EOF  
cat sqlite.sql | sqlite3 /opt/ooce/etc/certdb.db
* 创建配置文件以开启数据库访问
cat << EOF > /opt/ooce/etc/sqlite_db.json  
{"driver":"sqlite3","data_source":"/opt/ooce/etc/certdb.db"}  
EOF  

cat << EOF > ocsp-csr.json  
{  
  "CN": "OCSP 签名者",  
  "key": {  
    "algo": "rsa",  
    "size": 4096  
  },  
  "names": [  
    {  
      "C": "SE",  
      "ST": ".",  
      "L": "Stockholm"  
    }  
  ]  
}  
EOF
* 创建或修改中间的Kubernetes证书颁发机构(CA),以便为OCSP和CRL设置URL。
cat << EOF > kubernetes-ca/kubernetes-ca-config.json  
{  
    "signing": {  
        "default": {  
            "auth_key": "key1",  
            "ocsp_url": "http://${CA_URL}:8889",  
            "crl_url": "http://${CA_URL}:8888/crl",  
            "expiry": "过期时间 168h"  
        },  
        "profiles": {  
            "中间证书": {  
              "auth_key": "key1",  
              "expiry": "过期时间 43800h",  
              "usages": [  
                "signing",  
                "key encipherment",  
                "cert sign",  
                "crl sign"  
              ],  
              "ca_constraint": {  
                "is_ca": true,  
                "max_path_len": 1  
              }  
            },  
            "ocsp": {  
              "auth_key": "key1",  
              "usages": [  
                "digital signature",  
                "OCSP 签名"  
              ],  
              "expiry": "过期时间 26280h"  
            },  
            "www": {  
                "auth_key": "key1",  
                "expiry": "过期时间 8760h",  
                "usages": [  
                    "signing",  
                    "key encipherment",  
                    "服务器认证"  
                ]  
            },  
            "kubelet": {  
                "expiry": "过期时间 8760h",  
                "auth_key": "key1",  
                "usages": [  
                    "signing",  
                    "key encipherment",  
                    "客户端认证",  
                    "服务器认证"  
                ]  
            },  
            "client": {  
                "auth_key": "key1",  
                "expiry": "过期时间 8760h",  
                "usages": [  
                    "signing",  
                    "key encipherment",  
                    "客户端认证"  
                ]  
            }  
        }  
    },  
  "auth_keys": {  
    "key1": {  
      "key": "${AUTH_KEY}",  
      "type": "standard"  
    }  
  }  
}  
EOF  
cfssl gencert -ca=kubernetes-ca/kubernetes-ca.pem -ca-key=kubernetes-ca/kubernetes-ca-key.pem -config=kubernetes-ca/kubernetes-ca-config.json -profile="ocsp" ocsp-csr.json |cfssljson -bare ocsp
* 把文件放到API要使用的位置里:

将 `kubernetes-ca/kubernetes-ca{{,-key}.pem,-config.json}` 和 `ocsp{,-key}.pem` 复制到 `/opt/ooce/etc/` 目录下。

* 创建一个 SMF(System Management Framework)方法脚本文件(例如对于 systemd 来说,这样做是有意义的,选择 `exec` 后的可执行参数):
cat << EOF > /lib/svc/method/cfssl  
#  
# 本文件的内容受以下许可的条款约束:  
# 通用开发和分发许可证("许可")。  
# 除非遵守该许可,否则您不得使用此文件。  
#  
# 您可以从 usr/src/OPENSOLARIS.LICENSE 或 http://www.opensolaris.org/os/licensing 获取许可副本。  
# 请参阅许可中规定的具体语言,了解许可的权限和限制。  
#  
# 在分发受保护的代码时,在每个文件中包含此 CDDL 标头,并在 usr/src/OPENSOLARIS.LICENSE 中包括许可文件。  
# 如适用,请在 CDDL 标头之后添加以下内容,使用方括号 "[]" 中的字段替换您自己的标识信息: 版权所有 [yyyy] [版权拥有者的姓名]  
#  
# CDDL 标头结束  
#  
#  
# 版权所有 © 2008 Sun Microsystems, Inc. 保留所有权利。  
# 使用受许可条款的约束。  
#  
#ident    "%Z%%M%    %I%    %E% SMI"  

#  
# 启动/停止客户端 LDAP 服务  
#  

. /lib/svc/share/smf_include.sh  

case "\$1" in  
'start')  
        exec /opt/ooce/bin/cfssl serve -address=0.0.0.0 -port=8888 \  
        -db-config=/opt/ooce/etc/sqlite_db.json \  
        -ca=/opt/ooce/etc/kubernetes-ca.pem -ca-key=/opt/ooce/etc/kubernetes-ca-key.pem \  
        -config=/opt/ooce/etc/kubernetes-ca-config.json \  
        -responder=/opt/ooce/etc/ocsp.pem \  
        -responder-key=/opt/ooce/etc/ocsp-key.pem  > /var/log/cfssl.log \  
        2>&1 &  
    ;;  

'stop')  
    exec /usr/bin/pkill cfssl  
    ;;  

*)  
    echo "用法: \$0 start 或 stop"  
    exit 1  
    ;;  
esac  
EOF  
chmod +x /lib/svc/method/cfssl
* 服务声明文件:
cat << EOF > /lib/svc/method/cfssl  
#  
# 本文件的内容受通用开发和分发许可证("许可")的约束。  
# 除非遵守许可协议中的条款,否则不得使用本文件。  
#  
# 您可以在usr/src/OPENSOLARIS.LICENSE或http://www.opensolaris.org/os/licensing/获取许可协议的副本。  
# 请参阅许可协议了解具体的条款规定,以确定许可和限制的条件。  
#  
# 分发受许可代码时,在每个文件中包含此CDDL标题的内容,并在usr/src/OPENSOLARIS.LICENSE处包含许可文件。  
# 如适用,请在CDDL标题下方加上以下内容,用方括号"[]"中的字段替换您自己的标识信息: 版权所有[yyyy] [版权所有者姓名]  
#  
# CDDL标题结束  
#  
#  
# 版权 © 2008 Sun Microsystems, Inc. 保留所有权利。  
# 使用受许可协议的约束。  
#  
#ident    "%Z%%M%    %I%    %E% SMI"  

#  
# 启动和停止客户端LDAP服务  
#  

. /lib/svc/share/smf_include.sh  

case "\$1" in  
'start')  
        exec /opt/ooce/bin/cfssl serve -address=0.0.0.0 -port=8888 \  
        -db-config=/opt/ooce/etc/sqlite_db.json \  
        -ca=/opt/ooce/etc/kubernetes-ca.pem -ca-key=/opt/ooce/etc/kubernetes-ca-key.pem \  
        -config=/opt/ooce/etc/kubernetes-ca-config.json \  
        -responder=/opt/ooce/etc/ocsp.pem \  
        -responder-key=/opt/ooce/etc/ocsp-key.pem  > /var/log/cfssl.log \  
        2>&1 &  
    ;;  

'stop')  
    exec /usr/bin/pkill cfssl  
    ;;  

*)  
    echo "用法: \$0 { start | stop }"  
    exit 1  
    ;;  
esac  
EOF  
chmod +x /lib/svc/method/cfssl
# 云配置工作节点

在之前的帖子中已经描述了工作节点的设置,这里我只简要描述 `runcmd:` 段落中的步骤。被注释的部分用作虚拟化 guest 的示例(我创建了一个模板并进行克隆以节省时间,因此不需要重新安装客户端二进制文件,如下解释):
runcmd:  
  - modprobe overlay   
  - modprobe br_netfilter  
  - sysctl --system 2>/dev/null  
  #- echo "deb [signed-by=/usr/share/keyrings/libcontainers-archive-keyring.gpg] https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_22.04/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list  
  #- echo "deb [signed-by=/usr/share/keyrings/libcontainers-crio-archive-keyring.gpg] https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.28/xUbuntu_22.04/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:1.28.list  
  #- mkdir -p /usr/share/keyrings /var/lib/kubelet  
  #- curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_22.04/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-archive-keyring.gpg  
  #- curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.28/xUbuntu_22.04/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-crio-archive-keyring.gpg  
  #- curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg  
  #- echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list  
  #- export DEBIAN_FRONTEND=noninteractive KUBECONFIG=/etc/kubernetes/admin.conf  
  #- DEBIAN_FRONTEND=noninteractive apt-get update -q -y   
  #- DEBIAN_FRONTEND=noninteractive apt-get install -y cri-o cri-o-runc apt-transport-https ca-certificates curl gnupg-agent software-properties-common jq golang-cfssl  
  #- systemctl daemon-reload  
  #- systemctl enable --now crio  
  #- DEBIAN_FRONTEND=noninteractive apt-get install -q -y kubelet=1.28.3-1.1 kubectl=1.28.3-1.1  
  #- DEBIAN_FRONTEND=noninteractive apt-mark hold kubelet kubectl  
  - |  
    curl -q -s -d '{"label": "primary"}' http://${CA_URL}:8888/api/v1/cfssl/info  |jq -r '.result.certificate' > /var/lib/kubelet/ca.pem  
  - |  
    cat <<CIEOF > /var/lib/kubelet/worker-csr.json  
    {  
      "CN": "system:node:\$(cat /etc/hostname)",  
      "key": {  
        "algo": "rsa",  
        "size": 2048  
      },  
      "hosts": [  
        "\$(cat /etc/hostname)",  
        "\$(ip -4 -br --json a |jq -r '.[1].addr_info[].local')"  
      ],  
      "names": [  
        {  
          "O": "system:nodes"  
        }  
      ]  
    }  
    CIEOF  
  - |  
    cat <<CIEOF | cfssl gencert -config /dev/stdin -profile=client -profile=kubelet /var/lib/kubelet/worker-csr.json  |cfssljson -bare /var/lib/kubelet/worker  
    {  
     "auth_keys" : {  
        "key1" : {  
           "type" : "standard",  
           "key" : "${AUTH_KEY}"  
        }  
     },  
     "signing" : {  
        "default" : {  
           "auth_remote" : {  
              "remote" : "cfssl_server",  
              "auth_key" : "key1"  
           }  
        }  
     },  
     "remotes" : {  
        "cfssl_server" : "${CA_URL}"  
     }  
    }  
    CIEOF  
  - KUBECONFIG=/var/lib/kubelet/kubeconfig kubectl config set-cluster default-cluster --server=https://${K8S_API}:6443 --certificate-authority /var/lib/kubelet/ca.pem --embed-certs  
  - KUBECONFIG=/var/lib/kubelet/kubeconfig kubectl config set-credentials system:node:\$(cat /etc/hostname) --client-key /var/lib/kubelet/worker-key.pem --client-certificate /var/lib/kubelet/worker.pem --embed-certs  
  - KUBECONFIG=/var/lib/kubelet/kubeconfig kubectl config set-context default-system --cluster default-cluster --user system:node:\$(cat /etc/hostname)  
  - KUBECONFIG=/var/lib/kubelet/kubeconfig kubectl config use-context default-system  
  - systemctl enable --now kubelet

这里将发生的情况是,工作节点将获取CA证书作为基础,利用其主机名和IP地址来生成证书签名请求。

通过CFSSL API接口,CA将回复工作节点(Worker Node)的证书和密钥。

我一直在成功地运行这个来自动加入正在运行的作为bhyve客机的工作节点,一个RK1节点(Rockchip RK3558),一个CM4节点,以及一个通过pxe和cloud-init/autoinstall安装的裸机节点。

敬请期待…


这篇关于Kubernetes工作节点的自动加入方法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程