日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

自建Kubernetes集群實現節點自動伸縮

重要

本文中含有需要您注意的重要提示信息,忽略該信息可能對您的業務造成影響,請務必仔細閱讀。

如果您是自建的Kubernetes集群,且期望根據實際工作負載動態調整工作節點數量,確保資源的有效利用并維持服務的穩定性,可通過Cluster Autoscaler和阿里云彈性伸縮實現。

重要

本文采用手動部署Cluster Autocaler的方式實現K8s節點彈性伸縮。除了此方式之外,您可以將您的自建Kubernetes集群接入到ACK One注冊集群中,通過ACK One的自動彈性伸縮能力實現節點的自動伸縮。您可以參考以下步驟實現此功能。

  1. 將自建Kubernetes接入到ACK One。

  2. 為ACK One創建自動伸縮節點池。

更多ACK One的信息,請參見ACK One概述

工作原理

Cluster AutoScaler(簡稱CA)是一個自動擴展和收縮Kubernetes集群節點的組件。CA會定期檢測是否有因資源不足而處于Pending狀態的Pod,如果有,會驅動伸縮組進行擴容,其工作原理如下圖所示:

image

CA在監測到某些節點資源使用率持續低于預設的閾值,且這些節點上的Pod能夠遷移到其他節點時,會先將Pod驅逐到其他節點,之后驅動伸縮組進行縮容,其工作原理如下圖所示:

image

更多Cluster AutoScaler的信息,請參見Cluster Autoscaling官方介紹。

準備工作

在操作前,請確保您已經完成以下工作。

  • 已自建Kubernetes集群,且集群版本在v1.9.3及以上。

    重要

    本文檔基于在阿里云ECS上搭建的K8s集群進行測試,如果涉及云下IDC機器、跨云供應商等混合云場景,建議參考VPN網關或者智能接入網關等產品解決網絡連通性問題。

  • 創建RAM用戶。

    當CA需要訪問阿里云ESS時,必須先通過訪問憑證來驗證身份信息和訪問權限。您需要為CA創建RAM用戶并授予訪問ESS的權限。

    1. 創建一個RAM用戶,并開啟OpenAPI訪問控制。具體操作,請參見創建RAM用戶。

    2. 為RAM用戶授權以下自定義權限策略。如何為RAM用戶授權,請參見為RAM用戶授權。

      {
        "Version": "1",
        "Statement": [
          {
            "Action": [
              "ess:Describe*",
              "ess:CreateScalingRule",
              "ess:ModifyScalingGroup",
              "ess:RemoveInstances",
              "ess:ExecuteScalingRule",
              "ess:ModifyScalingRule",
              "ess:DeleteScalingRule",
              "ess:DetachInstances",
              "ecs:DescribeInstanceTypes"
            ],
            "Resource": [
              "*"
            ],
            "Effect": "Allow"
          }
        ]
      }
    3. 創建AccessKey并保存AccessKey ID和AccessKey Secret,在后續步驟中會使用。如何創建AccessKey,請參見創建AccessKey。

操作步驟

(可選)步驟一:構建Cluster AutoScaler鏡像

通過源碼構建自己的Cluster AutoScaler鏡像,該鏡像用于在您的K8s集群部署Cluster AutoScaler。

重要

您可以直接跳過此步驟,直接使用阿里云已構建好的cluster-autoscaler鏡像:ess-cluster-autoscaler-registry.cn-hangzhou.cr.aliyuncs.com/ess-cluster-autoscaler/cluster-autoscaler:v1.7。

  1. 從Github下載源碼。

    mkdir -p $GOPATH/src/github.com/kubernetes
    cd $GOPATH/src/github.com/kubernetes
    git clone https://github.com/kubernetes/autoscaler.git
    cd autoscaler
  2. 構建鏡像。

    # 編譯
    cd cluster-autoscaler && make build-arch-amd64
    # 構建鏡像
    docker build -t cluster-autoscaler:v1.0 -f Dockerfile.amd64 .
    # 打Tag
    docker tag cluster-autoscaler:v1.0 您的鏡像倉庫域名/cluster-autoscaler:v1.0
    # 上傳鏡像
    docker push 您的鏡像倉庫域名/cluster-autoscaler:v1.0

步驟二:創建并配置伸縮組

  1. 創建伸縮組。

    1. 登錄阿里云彈性伸縮控制臺。

    2. 在頂部菜單欄選擇可用區,在左側點擊伸縮組管理,點擊創建伸縮組

    3. 通過表單創建頁簽下,完成伸縮組配置,然后點擊創建按鈕。本示例采用以下配置,更多關于伸縮組的配置說明,請參見創建伸縮組。

      配置項

      說明

      示例

      伸縮組名稱

      輸入伸縮組名稱,格式參照界面提示。

      K8s-Node-Scaling-Group

      伸縮組類型

      選擇ECS,表示伸縮組內的實例類型為ECS實例。

      ECS

      組內實例配置信息來源

      先不指定自動創建實例的模板。伸縮組創建完成后,您需要繼續創建伸縮配置。

      從零開始創建

      組內最小實例數

      代表伸縮組最少有0臺ECS實例。

      0

      組內最大實例數

      代表伸縮組最大有5臺ECS實例。

      5

      專有網絡

      該伸縮組下創建的ECS實例會在此專有網絡下。

      vpc-test****-001

      選擇交換機

      您可以配置多個可用區的交換機以提高擴容成功率。

      vsw-test****

      重要

      在伸縮組創建完成后,請記錄您的可用區伸縮組ID以供后續步驟使用。

  2. 為伸縮組創建伸縮配置。

    1. 找到剛剛創建的伸縮組,點擊查看詳情進入伸縮組詳情頁。

    2. 實例配置來源頁簽下,點擊伸縮配置,點擊創建伸縮配置按鈕進入創建伸縮配置頁。

    3. 本實例采用以下配置,更多關于創建伸縮配置的說明,請參見創建伸縮配置(ECS實例)

      配置項

      說明

      示例

      伸縮配置名稱

      輸入伸縮配置名稱,格式參考界面提示。

      K8s-Scaling-Node-Config

      付費模式

      可以根據您的需求選擇。

      按量付費

      實例配置方式

      可以根據您的需求選擇。

      指定實例規格

      選擇實例規格

      可以根據您的需求選擇。

      警告

      該功能支持的實例規格如下:

      • 企業級x86計算規格族群。

      • 企業級異構計算規格族群。

      • 高性能計算實例規格族群。

      • 彈性裸金屬服務器規格族群。

      暫不支持企業級ARM計算規格族群。關于實例規格族的說明,請參見:實例規格族。

      ecs.g6a.large

      選擇鏡像

      根據您的需求選擇合適的鏡像。

      Alibaba Cloud Linux

    4. 配置網絡和安全組

      • 安全組:選擇安全組請確保該安全組可以連接到您Kubernetes集群所在網絡。

      • 分配公網IPv4地址:如果您的Kubernetes集群的API Server地址為公網IP,則需要勾選,為實例配置公網訪問能力。

        警告

        如果您的Kubernetes集群的API Server地址為公網IP,請確保您的Kubernetes集群的API Server已放開6443端口。

    5. 配置高級設置 > 實例自定義數據,請在實例自定義數據中填入以下腳本,用于初始化Kubernetes Worker節點環境并將Worker節點加入Kubernetes集群。

      重要

      將<<YOUR_MASTER_NODE_IP>>替換為您的Kubernetes的主節點IP。

      #!/bin/bash
      
      #關閉防火墻
      systemctl stop firewalld
      
      systemctl disable firewalld
      
      #關閉selinux
      sed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久
      setenforce 0  # 臨時
      
      #關閉swap
      swapoff -a  # 臨時
      sed -ri 's/.swap./#&/' /etc/fstab    # 永久
      
      #將橋接的IPv4流量傳遞到iptables的鏈
      cat > /etc/sysctl.d/k8s.conf << EOF
      net.bridge.bridge-nf-call-ip6tables = 1
      net.bridge.bridge-nf-call-iptables = 1
      EOF
      sysctl --system  # 生效
      
      
      #增加Kubernetes 源
      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
      
      
      #通用安裝包
      yum install vim bash-completion net-tools gcc -y
      
      #安裝Docker
      wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
      yum -y install docker-ce
      
      systemctl enable docker && systemctl start docker
      
      cat > /etc/docker/daemon.json << EOF
      {
        "exec-opts": ["native.cgroupdriver=systemd"]
      }
      EOF
      
      systemctl restart docker
      
      
      # 安裝kubeadm、kubectl、kubelet
      yum install -y kubelet-1.23.0 kubeadm-1.23.0 kubectl-1.23.0
      
      # 啟動kubelet服務
      systemctl enable kubelet && systemctl start kubelet
      
      #如果kubelet起不來,通過這個命名排查:journalctl -xeu kubelet
      
      #Worker節點加入集群
      regionId=$(sed -n 's/.*"region-id": "\(.*\)".*/\1/p' /run/cloud-init/instance-data.json)
      instanceId=$(sed -n 's/.*"instance_id": "\(.*\)".*/\1/p' /run/cloud-init/instance-data.json)
      privateIpv4=$(sed -n 's/.*"private-ipv4": "\(.*\)".*/\1/p' /run/cloud-init/instance-data.json)
      
      cat > kubeadm-config.yaml << EOF
      apiVersion: kubeadm.k8s.io/v1beta2
      kind: JoinConfiguration
      discovery:
        bootstrapToken:
          token: "your-bootstrap-token"
          apiServerEndpoint: "<<YOUR_MASTER_NODE_IP>>:6443"
          caCertHashes:
          - "sha256:your-discovery-token-ca-cert-hash"
      nodeRegistration:
        name: "$regionId-$privateIpv4"
        kubeletExtraArgs:
          provider-id: "$regionId.$instanceId"
      
      EOF
      
      kubeadm join --config=kubeadm-config.yaml
      說明

      需要在擴容時為worker節點指定--provider-id,文中的腳本已實現此功能。

    6. 點擊創建,并確保伸縮配置已生效。

  3. (可選)驗證伸縮組擴容實例是否可以正常加入K8s集群。

    您可以通過手動修改伸縮組最小實例數為1來擴容一臺ECS實例,并觀察擴容出來的ECS實例是否已經初始化并正常加入您的K8s集群。

步驟三:在K8s集群部署Cluster AutoScaler組件

  1. 將準備工作的RAM用戶的AccessKey ID和AccessKey Secret作Base64轉換。

    echo $AccessKey-ID | tr -d '\n' | base64
    echo $AccessKey-Secret | tr -d '\n' | base64 
    echo $RegionId | tr -d '\n' | base64
  2. 新建deploy-ca.yaml,內容如下,修改其中的相關字段信息后,部署到您K8s集群的kube-system命名空間。

    重要

    更新Secret的access-key-id、access-key-secret、region-id,以及在Deployment的容器啟動命令中,更新您的ESS伸縮組ID,具體操作如下:

    • 將<<YOUR_ACCESS_KEY_ID>>替換為Base64轉換后的AccessKey ID。

    • 將<<YOUR_ACCESS_KEY_SECRET>>替換為Base64轉換后的AccessKey Secret。

    • 將<<YOUR_REGION_ID>>替換為Base64轉換后的RegionID,RegionID獲取請參見地域

    • 將<<YOUR_ESS_SCALING_GROUP_ID>>替換為您剛剛創建的伸縮組ID。

    • 講<<KUBERNETES_SERVICE_HOST>>替換為您的K8s集群ApiServer地址。

    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: cloud-config
    type: Opaque
    data:
      access-key-id: <<YOUR_ACCESS_KEY_ID>>
      access-key-secret: <<YOUR_ACCESS_KEY_SECRET>>
      region-id: <<YOUR_REGION_ID>>
    
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      labels:
        k8s-addon: cluster-autoscaler.addons.k8s.io
        k8s-app: cluster-autoscaler
      name: cluster-autoscaler
      namespace: kube-system
    
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: cluster-autoscaler
      labels:
        k8s-addon: cluster-autoscaler.addons.k8s.io
        k8s-app: cluster-autoscaler
    rules:
    - apiGroups: [""]
      resources: ["events","endpoints"]
      verbs: ["create", "patch"]
    - apiGroups: [""]
      resources: ["pods/eviction"]
      verbs: ["create"]
    - apiGroups: [""]
      resources: ["pods/status"]
      verbs: ["update"]
    - apiGroups: [""]
      resources: ["endpoints"]
      resourceNames: ["cluster-autoscaler"]
      verbs: ["get","update"]
    - apiGroups: [""]
      resources: ["nodes"]
      verbs: ["watch","list","get","update"]
    - apiGroups: [""]
      resources: ["namespaces","pods","services","replicationcontrollers","persistentvolumeclaims","persistentvolumes"]
      verbs: ["watch","list","get"]
    - apiGroups: ["extensions"]
      resources: ["replicasets","daemonsets"]
      verbs: ["watch","list","get"]
    - apiGroups: ["policy"]
      resources: ["poddisruptionbudgets"]
      verbs: ["watch","list"]
    - apiGroups: ["apps"]
      resources: ["statefulsets", "replicasets", "daemonsets"]
      verbs: ["watch","list","get"]
    - apiGroups: ["batch"]
      resources: ["jobs"]
      verbs: ["watch","list","get"]
    - apiGroups: ["storage.k8s.io"]
      resources: ["storageclasses", "csinodes", "csidrivers", "csistoragecapacities"]
      verbs: ["watch","list","get"]
    
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: cluster-autoscaler
      namespace: kube-system
      labels:
        k8s-addon: cluster-autoscaler.addons.k8s.io
        k8s-app: cluster-autoscaler
    rules:
    - apiGroups: [""]
      resources: ["configmaps"]
      verbs: ["create","list","watch"]
    - apiGroups: [""]
      resources: ["configmaps"]
      resourceNames: ["cluster-autoscaler-status", "cluster-autoscaler-priority-expander"]
      verbs: ["delete","get","update","watch"]
    
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: cluster-autoscaler
      labels:
        k8s-addon: cluster-autoscaler.addons.k8s.io
        k8s-app: cluster-autoscaler
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-autoscaler
    subjects:
      - kind: ServiceAccount
        name: cluster-autoscaler
        namespace: kube-system
    
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: cluster-autoscaler
      namespace: kube-system
      labels:
        k8s-addon: cluster-autoscaler.addons.k8s.io
        k8s-app: cluster-autoscaler
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: cluster-autoscaler
    subjects:
      - kind: ServiceAccount
        name: cluster-autoscaler
        namespace: kube-system
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: cluster-autoscaler
      name: cluster-autoscaler
      namespace: kube-system
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: cluster-autoscaler
      template:
        metadata:
          labels:
            app: cluster-autoscaler
        spec:
          dnsPolicy: "None"
          dnsConfig:
            nameservers:
              - 100.100.2.136
              - 100.100.2.138
            options:
              - name: timeout
                value: "1"
              - name: attempts
                value: "3"
          priorityClassName: system-cluster-critical
          serviceAccountName: cluster-autoscaler
          containers:
            - command:
                - ./cluster-autoscaler
                - '--v=2'
                - '--logtostderr=true'
                - '--stderrthreshold=info'
                - '--cloud-provider=alicloud'
                - '--expander=least-waste'
                - '--scan-interval=60s'
                - '--scale-down-enabled=true'
                - '--scale-down-delay-after-add=10m'
                - '--scale-down-delay-after-failure=1m'
                - '--scale-down-unready-time=2m'
                - '--ok-total-unready-count=1000'
                - '--max-empty-bulk-delete=50'
                - '--leader-elect=false'
                - '--max-node-provision-time=5m'
                - '--scale-up-from-zero=true'
                - '--daemonset-eviction-for-empty-nodes=false'
                - '--daemonset-eviction-for-occupied-nodes=false'
                - '--max-graceful-termination-sec=14400'
                - '--skip-nodes-with-system-pods=true'
                - '--skip-nodes-with-local-storage=false'
                - '--min-replica-count=0'
                - '--scale-down-unneeded-time=10m'
                - '--scale-down-utilization-threshold=0.3'
                - '--scale-down-gpu-utilization-threshold=0.3'
                - '--nodes=0:100:<<YOUR_ESS_SCALING_GROUP_ID>>'
              image: >-
                ess-cluster-autoscaler-registry.cn-hangzhou.cr.aliyuncs.com/ess-cluster-autoscaler/cluster-autoscaler:v1.7
              imagePullPolicy: Always
              name: cluster-autoscaler
              resources:
                requests:
                  cpu: 100m
                  memory: 300Mi
              securityContext:
                allowPrivilegeEscalation: true
                capabilities:
                  add:
                    - SYS_ADMIN
                  drop:
                    - ALL
              env:
              - name: ACCESS_KEY_ID
                valueFrom:
                  secretKeyRef:
                    name: cloud-config
                    key: access-key-id
              - name: ACCESS_KEY_SECRET
                valueFrom:
                  secretKeyRef:
                    name: cloud-config
                    key: access-key-secret
              - name: REGION_ID
                valueFrom:
                  secretKeyRef:
                    name: cloud-config
                    key: region-id
              - name: KUBERNETES_SERVICE_HOST
                value: "<<KUBERNETES_SERVICE_HOST>>"
              - name: KUBERNETES_SERVICE_PORT
                value: "6443"
              - name: KUBERNETES_SERVICE_PORT_HTTPS
                value: "6443"
    說明
    • 通過參數--scale-down-enabled可以控制是否開啟縮容。如果開啟縮容,CA定期會檢測集群狀態,判斷當前集群狀態下,哪些節點資源利用率小于50%(通過參數--scale-down-utilization-threshold控制)。

    • CA默認不會終止kube-system命名空間的Pods,可以通過指定--skip-nodes-with-system-pods=false來覆蓋此默認設置。

    • CA的縮容操作默認會等待10分鐘,可以通過指定--scale-down-delay來修改等待時長,例如--scale-down-delay=5m

    • 如果運行在多個伸縮組上,--expander參數支持3種選項:random、most-podsleast-waste。

      • random:擴容時隨機選擇一個伸縮組。

      • most-pods:在擁有最多Pod的伸縮組上擴容。

      • least-waste:在浪費最少CPU/內存的伸縮組上擴容。如果多個伸縮組判定一致,會回退到隨機模式。

    通過以下命令部署CA到K8s集群。

    kubectl apply -f deploy-ca.yaml -n kube-system

功能驗證(可選)

當集群中有因為資源不足而產生Pending狀態的Pod時,CA會驅動伸縮組擴容節點,當一個節點資源使用率持續低于預設的閾值時,CA會驅動伸縮組縮容節點。

  1. 部署一個簡單的nginx-demo.yaml,來驗證自動擴容功能,yaml文件內容如下:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-demo
    spec:
      selector:
        matchLabels:
          app: nginx-demo
      replicas: 2
      template:
        metadata:
          labels:
            app: nginx-demo
        spec:
          containers:
            - name: nginx
              image: ess-cluster-autoscaler-registry.cn-hangzhou.cr.aliyuncs.com/ess-cluster-autoscaler/nginx-demo:v1.0
              ports:
                - containerPort: 80
                  name: http
                - containerPort: 443
                  name: https
              resources:
                requests:
                  memory: 1Gi
                  cpu: 1
                limits:
                  memory: 1Gi
                  cpu: '1'

    使用以下命令部署nginx-demo.yaml:

    kubectl apply -f nginx-demo.yaml
  2. 根據集群當前的Node資源空閑情況,通過增加replicas數量來產生因資源不足而Pending的Pod。使用以下命令增加replicas數量:

    kubectl scale deployment nginx-demo --replicas=5
  3. 等待1分鐘左右,觀察伸縮組是否發生擴容。

  4. 伸縮組實例擴容完成后,等待3分鐘,觀察新節點是否加入集群中,使用以下命令查看集群所有Node,觀察是否有新的Node節點加入K8s集群:

    kubectl get nodes
說明

驗證縮容時,您可以通過減少nginx-demo的副本數量來降低節點的使用率使其低于閾值,并觀察伸縮組是否發縮容活動來判斷縮容是否成功。