如何基於國產CPU的雲平臺構建容器管理平臺?(下篇)

隨着「中興事件」不斷升級,引發了國人對國產自主可控技術的高度關注;本人做爲所在單位的運維工程師,也但願能找到一個穩定、能兼容國產CPU的一整套架構方案,來構建IaaS平臺和PaaS平臺,知足單位對安全自主可控的需求。要基於全國產方式解決公司業務需求至少要在軟硬件層面知足,而國內基本都是基於x86解決方案,想找到知足需求的國產化解決方案仍是很是困難的事情。但筆者因爲一個偶然的機會,接觸到了國產的芯片廠商和雲計算廠商,並得知他們已經實現了全國產化的雲計算平臺,筆者也親自動手體驗了安裝部署該雲計算平臺,並在其之上安裝部署了容器平臺。上篇我給你們分享了國產CPU的服務器華芯通和國產雲平臺ZStack試用體驗,接下來將爲你們詳細分享如何基於ZStack雲主機構建K8S集羣。node

第三節 基於ZStack雲主機構建K8S集羣

這裏要提一下,爲何咱們不直接使用物理ARM服務器部署K8S集羣,這跟單位測試場景有關係,既要使用雲主機透傳GPU計算卡進行大量的計算,又要實現容器管理平臺。何況國外主流的K8S集羣一般是跑在虛擬機裏面的,運行在虛擬機裏面的好處有不少,好比能夠實現資源定製分配、利用雲平臺API接口能夠快速生成K8S集羣Node節點、更好的靈活性以及可靠性;在ZStack ARM雲平臺上能夠同時構建IaaS+PaaS混合平臺,知足不一樣場景下的需求。linux

因爲篇幅有限下面先介紹一下如何在基於ZStack For ARM平臺中雲主機部署K8S集羣,整個部署過程大概花1小時(這主要是訪問部分國外網絡時不是很順暢)。git

集羣環境介紹: github

在本環境中用於構建K8S集羣所需的資源,爲基於ZStack構建的平臺上的雲主機:golang

ZStack雲主機K8S集羣架構docker

1、準備工做express

配置主機名apache

hostnamectl set-hostname K8S-Master
hostnamectl set-hostname K8S-Node1
hostnamectl set-hostname K8S-Node2
hostnamectl set-hostname K8S-Node3

全部雲主機上關閉swap分區 不然會報錯;該操做只需在雲主機環境下執行,物理機環境無需操做。json

sudo swapoff -a

二、安裝部署

2.1安裝Docker

step 1: 安裝必要的一些系統工具ubuntu

sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common

step 2: 安裝GPG證書

curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

Step 3: 寫入軟件源信息

sudo add-apt-repository "deb [arch=arm64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"

Step 4: 更新並安裝 Docker-CE

sudo apt-get -y update
sudo apt-get -y install docker-ce

使用daocloud對docker鏡像下載進行加速

curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://56d10455.m.daocloud.io

2.2安裝go環境

apt-get install golang- golang

2.3 安裝kubelet、kubeadm、kubectl

apt-get update && apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubectl kubeadm kubectl

2.4用kubeadm建立集羣

初始化Master
kubeadm init --apiserver-advertise-address  172.120.194.196 --pod-network-cidr 10.244.0.0/16 
執行完上面命令後,若是中途不報錯會出現相似如下信息:
  kubeadm join 172.120.194.196:6443 --token oyf6ns.whcoaprs0q7growa --discovery-token-ca-cert-hash sha256:30a459df1b799673ca87f9dcc776f25b9839a8ab4b787968e05edfb6efe6a9d2
這段信息主要是提示如何註冊其餘節點到K8S集羣。

2.5 配置kubectl

Kubectl是管理K8S集羣的命令行工具,所以須要對kubectl運行環境進行配置。
su - zstack
sudo mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
echo "source <(kubectl completion bash)" >> ~/.bash

2.6 安裝Pod網絡

爲了讓K8S集羣的Pod之間可以正常通信,必須安裝Pod網絡,Pod網絡能夠支持多種網絡方案,當前測試環境採用Flannel模式。
先將Flannel的yaml文件下載到本地,進行編輯,編輯的主要目的是將原來X86架構的鏡像名稱,改成ARM架構的。讓其可以在ZStack ARM雲環境正常運行。修改位置及內容參考下面文件中紅色粗體字部分。
sudo wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
vim kube-flannel.yml
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: flannel
rules:
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes/status
    verbs:
      - patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: flannel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
- kind: ServiceAccount
  name: flannel
  namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: flannel
  namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-flannel-cfg
  namespace: kube-system
  labels:
    tier: node
    app: flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: kube-flannel-ds
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      hostNetwork: true
      nodeSelector:
        beta.kubernetes.io/arch: arm64
      tolerations:
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.10.0-arm64
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.10.0-arm64
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: true
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg

sudo kubectl apply -f   kube-flannel.yml
執行上面命令後會正常狀況下會有以下輸出:
clusterrole.rbac.authorization.k8s.io "flannel" created
clusterrolebinding.rbac.authorization.k8s.io "flannel" created
serviceaccount "flannel" created
configmap "kube-flannel-cfg" created
daemonset.extensions "kube-flannel-ds" created

2.7註冊節點到K8S集羣

分別在K8S-Node一、K8S-Node二、K8S-Node3

kubeadm join 172.120.194.196:6443 --token oyf6ns.whcoaprs0q7growa --discovery-token-ca-cert-hash sha256:30a459df1b799673ca87f9dcc776f25b9839a8ab4b787968e05edfb6efe6a9d2

kubectl get nodes 查看節點狀態

zstack@K8S-Master:~$ kubectl get nodes

NAME STATUS ROLES AGE VERSION

k8s-master Ready master 49m v1.11.0

k8s-node1 NotReady 4m v1.11.0

k8s-node2 NotReady 4m v1.11.0

k8s-node3 NotReady 4m v1.11.0

若是發現全部節點是NotReady 是因每一個節點都須要啓動若干個組件,這些組件都是在Pod中運行,且須要到Google下載鏡像。使用下面命令查看Pod運行情況:

kubectl get pod --all-namespaces  正常狀況應該是以下的狀態:
NAMESPACE     NAME                                 READY     STATUS    RESTARTS   AGE
kube-system   coredns-78fcdf6894-49tkw             1/1       Running   0          1h
kube-system   coredns-78fcdf6894-gmcph             1/1       Running   0          1h
kube-system   etcd-k8s-master                      1/1       Running   0          19m
kube-system   kube-apiserver-k8s-master            1/1       Running   0          19m
kube-system   kube-controller-manager-k8s-master   1/1       Running   0          19m
kube-system   kube-flannel-ds-bqx2s                1/1       Running   0          16m
kube-system   kube-flannel-ds-jgmjp                1/1       Running   0          16m
kube-system   kube-flannel-ds-mxpl8                1/1       Running   0          21m
kube-system   kube-flannel-ds-sd6lh                1/1       Running   0          16m
kube-system   kube-proxy-cwslw                     1/1       Running   0          16m
kube-system   kube-proxy-j75fj                     1/1       Running   0          1h
kube-system   kube-proxy-ptn55                     1/1       Running   0          16m
kube-system   kube-proxy-zl8mb                     1/1       Running   0          16m
kube-system   kube-scheduler-k8s-master            1/1       Running   0          19m
在整個過程當中若是發現狀態爲Pending、ContainerCreateing、ImagePullBackOff等狀態都表示Pod還未就緒,只有Running狀態纔是正常的。要作的事情只有等待。

kubectl get nodes 再次查看節點狀態

NAME STATUS ROLES AGE VERSION

k8s-master Ready master 1h v1.11.0

k8s-node1 Ready 16m v1.11.0

k8s-node2 Ready 16m v1.11.0

k8s-node3 Ready 16m v1.11.0

當全部節點均爲 Ready狀時,此時就可使用這個集羣了

2.8部署kubernetes-dashboard

克隆kubernetes-dashboard yaml文件

sudo git clone https://github.com/gh-Devin/kubernetes-dashboard.git

修改kubernetes-dashboard yaml文件,修改內容爲下面紅色粗體部分。

cd kubernetes-dashboard/
vim kubernetes-dashboard.yaml
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Configuration to deploy release version of the Dashboard UI compatible with
# Kubernetes 1.8.
#
# Example usage: kubectl create -f <this_file>

# ------------------- Dashboard Secret ------------------- #

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-certs
  namespace: kube-system
type: Opaque

---
# ------------------- Dashboard Service Account ------------------- #

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system

---
# ------------------- Dashboard Role & Role Binding ------------------- #

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
rules:
  # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["create"]
  # Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["create"]
  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
  verbs: ["get", "update", "delete"]
  # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["kubernetes-dashboard-settings"]
  verbs: ["get", "update"]
  # Allow Dashboard to get metrics from heapster.
- apiGroups: [""]
  resources: ["services"]
  resourceNames: ["heapster"]
  verbs: ["proxy"]
- apiGroups: [""]
  resources: ["services/proxy"]
  resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
  verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard-minimal
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system

---
# ------------------- Dashboard Deployment ------------------- #

kind: Deployment
apiVersion: apps/v1beta2
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
    spec:
      serviceAccountName: kubernetes-dashboard
      containers:
      - name: kubernetes-dashboard
        image: k8s.gcr.io/kubernetes-dashboard-arm64:v1.8.3
        ports:
        - containerPort: 9090
          protocol: TCP
        args:
          #- --auto-generate-certificates
          # Uncomment the following line to manually specify Kubernetes API server Host
          # If not specified, Dashboard will attempt to auto discover the API server and connect
          # to it. Uncomment only if the default does not work.
        volumeMounts:
        - name: kubernetes-dashboard-certs
          mountPath: /certs
          # Create on-disk volume to store exec logs
        - mountPath: /tmp
          name: tmp-volume
        livenessProbe:
          httpGet:
            scheme: HTTP
            path: /
            port: 9090
          initialDelaySeconds: 30
          timeoutSeconds: 30
      volumes:
      - name: kubernetes-dashboard-certs
        secret:
          secretName: kubernetes-dashboard-certs
      - name: tmp-volume
        emptyDir: {}
      serviceAccountName: kubernetes-dashboard-admin
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule

---
# ------------------- Dashboard Service ------------------- #

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  ports:
    - port: 9090
      targetPort: 9090
  selector:
    k8s-app: kubernetes-dashboard

# ------------------------------------------------------------
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-external
  namespace: kube-system
spec:
  ports:
    - port: 9090
      targetPort: 9090
      nodePort: 30090
  type: NodePort
  selector:
k8s-app: kubernetes-dashboard
修改完成後執行 
kubectl  -n kube-system create -f .
執行命令的正常輸出:
serviceaccount "kubernetes-dashboard-admin" created
clusterrolebinding.rbac.authorization.k8s.io "kubernetes-dashboard-admin" created
secret "kubernetes-dashboard-certs" created
serviceaccount "kubernetes-dashboard" created
role.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
rolebinding.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
deployment.apps "kubernetes-dashboard" created
service "kubernetes-dashboard-external" created

而後查看kubernetes-dashboard Pod的狀態
kubectl get pod --all-namespaces

NAMESPACE     NAME                                    READY     STATUS    RESTARTS   AGE
kube-system   kubernetes-dashboard-66885dcb6f-v6qfm   1/1       Running   0          8m

當狀態爲running 時執行下面命令 查看端口
kubectl --namespace=kube-system describe svc kubernetes-dashboard
Name:                     kubernetes-dashboard-external
Namespace:                kube-system
Labels:                   k8s-app=kubernetes-dashboard
Annotations:              <none>
Selector:                 k8s-app=kubernetes-dashboard
Type:                     NodePort
IP:                       10.111.189.106
Port:                     <unset>  9090/TCP
TargetPort:               9090/TCP
NodePort:                 <unset>  30090/TCP     此端口爲外部訪問端口
Endpoints:                10.244.2.4:9090
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

注意:若是在部署K8S-Dashboard界面過程當中若是則登陸UI的時候會報錯:

這是由於K8S在1.6版本之後啓用了RBAC訪問控制策略,可使用kubectl或Kubernetes API進行配置。使用RBAC能夠直接受權給用戶,讓用戶擁有受權管理的權限,這樣就再也不須要直接觸碰Master Node。按照上面部署步驟則能夠避免。

至此,基於ARM環境的K8S集羣就部署完成了。

第四節 全篇總結

先說說關於ZStack安裝部署的一些心得,整個ZStack For ARM平臺部署到業務環境構建的過程,都是比較流暢的。ZStack產品化程度高,安裝過程很是簡單,基本上按照官方部署文檔1個小時內就能完成3臺規模的雲平臺搭建及平臺初始化工做。

ZStack雲平臺採用獨特的異步架構,大大提高了平臺響應能力,使得批量併發操做再也不成爲煩惱;管理層面與業務層面獨立,不會由於管理節點意外宕機致使業務中斷;平臺內置大量實用性很高的功能,極大方便了在測試過程當中運維任務;版本升級簡單可靠,徹底實現5分鐘跨版本無縫升級,經實測升級過程當中徹底不影響業務正常運行。經過升級後能實現異構集羣管理,也就是說在ARM服務器上構建管理節點,能夠同時管理ARM集羣中的資源,也能管理X86架構集羣中的資源;同時實現高級SDN功能。

而基於ZStack雲主機構建K8S集羣時,咱們團隊在選擇方案的時候,也拿物理機和雲主機作過一系列對比,對比以後發現當我用ZStack雲主機部署K8S集羣的時候更加靈活、可控。具體的能夠在如下幾個方面體現:

一、ZStack雲主機天生隔離性好

對容器技術瞭解的人應該清楚,多個容器公用一個Host Kernel;這樣就會遇到隔離性方面的問題,雖然隨着技術發展,目前也可使用Linux系統上的防禦機制實現安全隔離,可是從某個層面講並非徹底隔離,而云主機方式受益於虛擬化技術,天生就有很是好的隔離性,從而能夠進一步保障安全。ZStack就是基於KVM虛擬化技術架構自研。

二、受益於ZStack雲平臺多租戶

在物理服務器上運行的大堆容器要實現資源自理,所謂資源自理就是各自管理本身的容器資源,那麼這個時候問題就來了,一臺物理機上有成千上萬個容器怎麼去細分管理範圍呢?這個時候雲平臺的多租戶管理就派上用處了,每一個租戶被分配到相應的雲主機,各自管理各自的雲主機以及容器集羣。同時還能對不一樣人員權限進行控制管理。在本次測試的ZStack For ARM雲平臺,就能夠實現按企業組織架構方式進行資源、權限管理,同時還能實現流程審批,審批完成後自動建立所需的雲主機;聽說後面發佈的ZStack2.5.0版本還有資源編排功能。

3.ZStack雲平臺靈活性、自動化程度高

經過ZStack,能夠根據業務需求,對雲主機進行資源定製,減小資源浪費。同時根據自身業務狀況調整架構實現模式,好比:有計算密集型業務,此時能夠藉助GPU透傳功能,將GPU透傳到雲主機,能快速實現計算任務,避免過多繁瑣配置。

另外目前各類雲平臺都有相應API接口,能夠方便第三方應用直接調用,從而實現根據業務壓力自動進行資源伸縮。可是對於物理服務器來講沒什麼完整的API接口,基本上都是基於IPMI方式進行管理,並且每一個廠商的IPMI還不通用,很難實現資源的動態伸縮。說到API接口,我瞭解到的ZStack雲平臺,具有全API接口開放的特色。可使容器集羣根據業務壓力自動伸縮。

四、可靠性很是好

爲何這麼說呢?其實不難理解,計劃內和計劃外業務影響少。當咱們對物理服務器進行計劃內維護時,那些單容器運行的業務一定會受影響,此時能夠藉助雲平臺中的熱遷移功能,遷移的過程當中可實現業務不中斷。對於計劃外停機,對業務影響基本上都是按天算的,損失不可言表。若是採用雲平臺方式業務中斷時間將會縮短到分鐘級別。

上面簡單分享了一下用雲主機構建K8S集羣的一些優勢,固然也有一些缺點,在我看來缺點無非就是性能有稍微點損失,總之利大於弊。能夠在規劃時規避掉這個問題,好比能夠將性能型容器資源集中放到物理Node上,這樣就能夠完美解決了。

最後再說說在ZStack ARM架構的雲主機上部署K8S須要注意的地方,爲你們提供一些參考。

一、默認Get下來的yaml配置文件,裏面涉及的image路徑都是x86架構的amd64,須要將其改爲arm64。

二、在建立集羣的時候,若是採用flannel網絡模式則--pod-network-cidr必定要爲 10.244.0.0/16,不然Pod網可能不通。

三、雲主機環境必定要執行sudo swapoff -a 否則建立K8S集羣的時候就會報錯。

以上就是我本次的主要分享內容,歡迎你們關注交流。(qq:410185063;mail:zts@viczhu.com)。

相關文章
相關標籤/搜索