1. 程式人生 > >龍芯電腦平臺kubernetes叢集編譯及部署方案

龍芯電腦平臺kubernetes叢集編譯及部署方案

timg.jpg

http://ask.loongnix.org/?/article/105
 一、環境
作業系統: loongnix
核心: 3.10.84
go版本: go1.9.2 linux/mips64le
cfssl(1.2.0)
etcd(3.2.12)
flannel(0.9.1)
kubernetes(1.9.0)
需自定義go 的環境變數,這裡設定的路徑為/usr/share/gocode

export GOPATH=/usr/share/gocode


三臺機器:
master:10.20.42.17
node:   10.20.42.22
node:   10.20.42.172
 
二、編譯cfssl原始碼


1.建立程式碼存放目錄
mkdir -p $GOPATH/src/github.com/cloudflare
2.下載並編譯原始碼
go get -u github.com/cloudflare/cfssl/cmd/cfssl
3.切換至二進位制檔案生成目錄並檢視檔案
ls $GOPATH/bin
 
三、編譯etcd原始碼
參考文章(龍芯公有云系列之一)搭建分散式儲存服務etcd
連結地址:http://ask.loongnix.org/?/article/93

四、編譯flannel原始碼
1.建立程式碼存放目錄
 mkdir -p $GOPATH/src/github.com/coreos
2.切換至該目錄並下載原始碼
cd $GOPATH/src/github.com/coreos
git clone https://github.com/coreos/flannel.git
3.開啟flannel資料夾,執行編譯過程
cd flannel/
go build
4.檢視編譯的二進位制檔案
ls flannel
 
五、編譯kubernetes原始碼

Kubernetes對golang版本的要求
Kubernetes    requires Go
1.0 - 1.2         1.4.2
1.3, 1.4          1.6
1.5, 1.6          1.7 - 1.7.5
1.7                 1.8.1
1.8                 1.8.3
1.9+               1.9.1
本文件編譯的Kubernetes為當前最新版本1.9.0;golang版本為1.9.2
 
Fork

1.訪問 https://github.com/kubernetes/kubernetes
2.點選右上角fork按鈕,fork一份程式碼到你的github帳號,方便後續的開發。
 
Clone fork 到本地
working_dir=$GOPATH/src/k8s.io
user=xxxx #你的github賬戶名
mkdir -p $working_dir
cd $working_dir
git clone https://github.com/$user/kubernetes.git
# 或: git clone [email protected]:$user/kubernetes.git

cd $working_dir/kubernetes
git remote add upstream https://github.com/kubernetes/kubernetes.git
# 或: git remote add upstream [email protected]:kubernetes/kubernetes.git

# 永遠不向upstream的master分支進行push操作:
git remote set-url --push upstream no_push

# 確認你的遠端配置生效
git remote -v

    origin    https://github.com/bearabby/kubernetes.git (fetch)
    origin    https://github.com/bearabby/kubernetes.git (push)
    upstream    https://github.com/kubernetes/kubernetes.git (fetch)
    upstream    no_push (push)

建立本地分支
cd $working_dir/kubernetes
git fetch upstream
git checkout master
git rebase upstream/master

git checkout -b loongsonfeature
 
Build
cd $working_dir/kubernetes
make

報錯資訊不多,多為一些函式或變數未對mips64le平臺進行支援。修改內容見0001-Build-on-mips64le.patch
注意記憶體剩餘不足會導致編譯出錯:”signal: killed”,解決辦法是通過增加交換分割槽。
 

六、搭建kubernetes叢集
1.拷貝二進位制檔案至/root/local/bin資料夾下
mkdir -p /root/local/bin
cp  $GOPATH/bin/cfssl  /root/local/bin 
cp  /usr/bin  /root/local/bin
cp $GOPATH/src/k8s.io/kubernetes/_output/local/go/bin/*  /root/local/bin
2.設定環境變數
export PATH=/root/local/bin:$PATH
3.設定部署叢集所需引數
cd /root    /local/bin
cat > environment.sh <<EOF 
#!/usr/bin/bash
# TLS Bootstrapping 使用的 Token,可以使用命令 head -c 16 /dev/urandom | od -An -t x | tr -d ' ' 生成
BOOTSTRAP_TOKEN="6c314aea8ff601079617b03df567e478"

# 最好使用 主機未用的網段 來定義服務網段和 Pod 網段
# 服務網段 (Service CIDR),部署前路由不可達,部署後集群內使用IP:Port可達
SERVICE_CIDR="10.254.0.0/16"

# POD 網段 (Cluster CIDR),部署前路由不可達,**部署後**路由可達(flanneld保證)
CLUSTER_CIDR="172.30.0.0/16"

# 服務埠範圍 (NodePort Range)
export NODE_PORT_RANGE="8400-9000"

# etcd 叢集服務地址列表
export ETCD_ENDPOINTS="https://10.20.42.17:2379,https://10.20.42.22:2379,https://10.20.42.172:2379"

# flanneld 網路配置字首
export FLANNEL_ETCD_PREFIX="/kubernetes/network"

# kubernetes 服務 IP (一般是 SERVICE_CIDR 中第一個IP)
export CLUSTER_KUBERNETES_SVC_IP="10.254.0.1"

# 叢集 DNS 服務 IP (從 SERVICE_CIDR 中預分配)
export CLUSTER_DNS_SVC_IP="10.254.0.2"

# 叢集 DNS 域名
export CLUSTER_DNS_DOMAIN="cluster.local."
EOF
 
4.建立 CA 證書和祕鑰
(1)建立 CA 配置檔案
 cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "8760h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "8760h"
      }
    }
  }
}
EOF
引數說明:
ca-config.json:可以定義多個 profiles,分別指定不同的過期時間、使用場景等引數;後續在簽名證書時使用某個 profile;
signing:表示該證書可用於簽名其它證書;生成的 ca.pem 證書中 CA=TRUE;
server auth:表示 client 可以用該 CA 對 server 提供的證書進行驗證;
client auth:表示 server 可以用該 CA 對 client 提供的證書進行驗證
(2)建立 CA 證書籤名請求:
cat > ca-csr.json <<EOF
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048建立 CA 證書和祕鑰

  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF
引數說明:
"CN":Common Name,kube-apiserver 從證書中提取該欄位作為請求的使用者名稱 (User Name);瀏覽器使用該欄位驗證網站是否合法;
"O":Organization,kube-apiserver 從證書中提取該欄位作為請求使用者所屬的組 (Group);
(3)生成 CA 證書和私鑰
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
(4)分發證書
拷貝證書到所有機器上(manager及node節點)
mkdir -p /etc/kubernetes/ssl
cp ca* /etc/kubernetes/ssl
 
5.部署高可用 etcd 叢集
這三個節點複用 kubernetes master 機器,分別命名
etcd-host0:10.20.42.17
etcd-host1:10.20.42.22
etcd-host2:10.20.42.172
(1)設定etcd所需環境變數
export NODE_NAME=etcd-host0 # 當前部署的機器名稱(隨便定義,只要能區分不同機器即可)
export NODE_IP=10.20.42.17 # 當前部署的機器 IP
export NODE_IPS="10.20.42.17 10.20.42.22 10.20.42.172" # etcd 叢集所有機器 IP
# etcd 叢集間通訊的IP和埠
export ETCD_NODES=etcd-host0=https://10.20.42.17:2380,etcd-host1=https://10.20.42.22:2380,etcd-host2=https://10.20.42.172:2380
# 匯入用到的其它全域性變數:ETCD_ENDPOINTS、FLANNEL_ETCD_PREFIX、CLUSTER_CIDR
source /root/local/bin/environment.sh
(2)建立 TLS 祕鑰和證書
cat > etcd-csr.json <<EOF
{
  "CN": "etcd",
  "hosts": [
    "127.0.0.1",
    "${NODE_IP}"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF
引數說明:hosts 欄位指定授權使用該證書的 etcd 節點 IP;
(3)生成 etcd 證書和私鑰:
cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
  -ca-key=/etc/kubernetes/ssl/ca-key.pem \
  -config=/etc/kubernetes/ssl/ca-config.json \
  -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
mkdir -p /etc/etcd/ssl
mv etcd*.pem /etc/etcd/ssl
(4)建立 etcd 的 systemd unit 檔案
mkdir -p /var/lib/etcd  # 必須先建立工作目錄
 cat > etcd.service <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Environment=ETCD_UNSUPPORTED_ARCH=mips64le
Type=notify
WorkingDirectory=/var/lib/etcd/
ExecStart=/root/local/bin/etcd \\
  --name=${NODE_NAME} \\
  --cert-file=/etc/etcd/ssl/etcd.pem \\
  --key-file=/etc/etcd/ssl/etcd-key.pem \\
  --peer-cert-file=/etc/etcd/ssl/etcd.pem \\
  --peer-key-file=/etc/etcd/ssl/etcd-key.pem \\
  --trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\
  --peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\
  --initial-advertise-peer-urls=https://${NODE_IP}:2380 \\
  --listen-peer-urls=https://${NODE_IP}:2380 \\
  --listen-client-urls=https://${NODE_IP}:2379,http://127.0.0.1:2379 \\
  --advertise-client-urls=https://${NODE_IP}:2379 \\
  --initial-cluster-token=etcd-cluster-0 \\
  --initial-cluster=${ETCD_NODES} \\
  --initial-cluster-state=new \\
  --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF
引數說明:
指定 etcd 的工作目錄和資料目錄為 /var/lib/etcd,需在啟動服務前建立這個目錄;
為了保證通訊安全,需要指定 etcd 的公私鑰(cert-file和key-file)、Peers 通訊的公私鑰和 CA 證書(peer-cert-file、peer-key-file、peer-trusted-ca-file)、客戶端的CA證書(trusted-ca-file);
--initial-cluster-state 值為 new 時,--name 的引數值必須位於 --initial-cluster 列表中;
 
(5)啟動etcd服務
mv etcd.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable etcd
systemctl start etcd
在所有的 etcd 節點重複上面的步驟,直到所有機器的 etcd 服務都已啟動。
(6)驗證服務
部署完 etcd 集群后,在任一 etcd 叢集節點上執行如下命令
for ip in ${NODE_IPS}; do
  ETCDCTL_API=3 /root/local/bin/etcdctl \
  --endpoints=https://${ip}:2379  \
  --cacert=/etc/kubernetes/ssl/ca.pem \
  --cert=/etc/etcd/ssl/etcd.pem \
  --key=/etc/etcd/ssl/etcd-key.pem \
  endpoint health; done

預期結果:
https://10.20.42.17:2379 is healthy: successfully committed proposal: took = 1.246915ms
https://10.20.42.22:2379 is healthy: successfully committed proposal: took = 1.509229ms
https://10.20.42.172:2379 is healthy: successfully committed proposal: took = 1.519269ms
三臺 etcd 的輸出均為 healthy 時表示叢集服務正常(忽略 warning 資訊)。
 
6.部署 kubectl 命令列工具

kubectl 預設從 ~/.kube/config 配置檔案獲取訪問 kube-apiserver 地址、證書、使用者名稱等資訊,如果沒有配置該檔案,執行命令時出錯:
kubectl get pods
The connection to the server localhost:8080 was refused - did you specify the right host or port?
下面介紹配置 kubernetes 叢集命令列工具 kubectl 的步驟。
需要將下載的 kubectl 二進位制程式和生成的 ~/.kube/config 配置檔案拷貝到所有使用 kubectl 命令的機器。
(1)部署 kubectl需要的變數
export MASTER_IP=10.64.3.7 
# 替換為 kubernetes master 叢集任一機器 IP
export KUBE_APISERVER="https://${MASTER_IP}:6443"
說明:
變數 KUBE_APISERVER 指定 kubelet 訪問的 kube-apiserver 的地址,後續被寫入 ~/.kube/config 配置檔案;
(2)建立 admin 證書
ubectl 與 kube-apiserver 的安全埠通訊,需要為安全通訊提供 TLS 證書和祕鑰。
建立 admin 證書籤名請求
cat > admin-csr.json <<EOF
{
  "CN": "admin",
  "hosts": ,
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}
EOF
引數說明:
後續 kube-apiserver 使用 RBAC 對客戶端(如 kubelet、kube-proxy、Pod)請求進行授權;
kube-apiserver 預定義了一些 RBAC 使用的 RoleBindings,如 cluster-admin 將 Group system:masters 與 Role cluster-admin 繫結,該 Role 授予了呼叫kube-apiserver 所有 API的許可權;
O 指定該證書的 Group 為 system:masters,kubelet 使用該證書訪問 kube-apiserver 時 ,由於證書被 CA 簽名,所以認證通過,同時由於證書使用者組為經過預授權的 system:masters,所以被授予訪問所有 API 的許可權;
hosts 屬性值為空列表
(3)生成 admin 證書和私鑰:
cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
  -ca-key=/etc/kubernetes/ssl/ca-key.pem \
  -config=/etc/kubernetes/ssl/ca-config.json \
  -profile=kubernetes admin-csr.json | cfssljson -bare admin
mv admin*.pem /etc/kubernetes/ssl/
rm admin.csr admin-csr.json
(4)建立 kubectl kubeconfig 檔案
# 設定叢集引數
 kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER}
# 設定客戶端認證引數
 kubectl config set-credentials admin \
  --client-certificate=/etc/kubernetes/ssl/admin.pem \
  --embed-certs=true \
  --client-key=/etc/kubernetes/ssl/admin-key.pem
 # 設定上下文引數
kubectl config set-context kubernetes \
  --cluster=kubernetes \
  --user=admin
 # 設定預設上下文
 kubectl config use-context kubernetes
引數說明:
admin.pem 證書 O 欄位值為 system:masters,kube-apiserver 預定義的 RoleBinding cluster-admin 將 Group system:masters 與 Role cluster-admin 繫結,該 Role 授予了呼叫kube-apiserver 相關 API 的許可權;
生成的 kubeconfig 被儲存到 ~/.kube/config 檔案;
(5)分發 kubeconfig 檔案
將 ~/.kube/config 檔案拷貝到執行 kubelet 命令的機器的 ~/.kube/ 目錄下。
 
7.部署 Flannel 網路

(1)使用的變數
export NODE_IP=10.20.42.17 # 當前部署節點的 IP
# 匯入用到的其它全域性變數:ETCD_ENDPOINTS、FLANNEL_ETCD_PREFIX、CLUSTER_CIDR
 source /root/local/bin/environment.sh
(2)建立 TLS 祕鑰和證書
  建立 flanneld 證書籤名請求
cat > flanneld-csr.json <<EOF
{
  "CN": "flanneld",
  "hosts": ,
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF
引數說明:
hosts 欄位為空;
生成 flanneld 證書和私鑰
cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
  -ca-key=/etc/kubernetes/ssl/ca-key.pem \
  -config=/etc/kubernetes/ssl/ca-config.json \
  -profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld
mkdir -p /etc/flanneld/ssl
mv flanneld*.pem /etc/flanneld/ssl
rm flanneld.csr  flanneld-csr.json
(3)向 etcd 寫入叢集 Pod 網段資訊
/root/local/bin/etcdctl \
  --endpoints=${ETCD_ENDPOINTS} \
  --ca-file=/etc/kubernetes/ssl/ca.pem \
  --cert-file=/etc/flanneld/ssl/flanneld.pem \
  --key-file=/etc/flanneld/ssl/flanneld-key.pem \
  set ${FLANNEL_ETCD_PREFIX}/config '{"Network":"'${CLUSTER_CIDR}'", "SubnetLen": 24, "Backend": {"Type": "vxlan"}}'
引數說明:
flanneld 目前版本 (v0.7.1) 不支援 etcd v3,故使用 etcd v2 API 寫入配置 key 和網段資料;
寫入的 Pod 網段(${CLUSTER_CIDR},172.30.0.0/16) 必須與 kube-controller-manager 的 --cluster-cidr 選項值一致;
(4)建立 flanneld 的 systemd unit 檔案
cat > flanneld.service << EOF
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service

[Service]
Type=notify
ExecStart=/root/local/bin/flannel \\
  -etcd-cafile=/etc/kubernetes/ssl/ca.pem \\
  -etcd-certfile=/etc/flanneld/ssl/flanneld.pem \\
  -etcd-keyfile=/etc/flanneld/ssl/flanneld-key.pem \\
  -etcd-endpoints=${ETCD_ENDPOINTS} \\
  -etcd-prefix=${FLANNEL_ETCD_PREFIX}
ExecStartPost=/root/local/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure

[Install]
WantedBy=multi-user.target
RequiredBy=docker.service
EOF
(5)啟動 flanneld
 cp flanneld.service /etc/systemd/system/
 systemctl daemon-reload
 systemctl enable flanneld
 systemctl start flanneld
 
出現錯誤:
I1218 11:00:26.022231 11623 main.go:482] Using interface with name enp5s0 and address 10.20.42.17
I1218 11:00:26.022478 11623 main.go:499] Defaulting external address to interface address (10.20.42.17)
2017-12-18 11:00:26.027271 I | warning: ignoring ServerName for user-provided CA for backwards compatibility is deprecated
I1218 11:00:26.027501 11623 main.go:234] Created subnet manager: Etcd Local Manager with Previous Subnet: 0.0.0.0/0
I1218 11:00:26.027560 11623 main.go:237] Installing signal handlers
I1218 11:00:26.197651 11623 main.go:347] Found network config - Backend type: vxlan
I1218 11:00:26.197811 11623 vxlan.go:119] VXLAN config: VNI=1 Port=0 GBP=false DirectRouting=false
E1218 11:00:26.200720 11623 main.go:279] Error registering network: operation not supported
I1218 11:00:26.200802 11623 main.go:327] Stopping shutdownHandler...
提示內容:網路註冊失敗
經查詢,原因為:當前loongnix系統核心版本為3.10,而vxlan的最低核心版本為3.14+,所以無法部署flannel,部署工作暫時中止

kubernetes原始碼及編譯後的二進位制檔案下載地址