Kubernetes叢集安裝文件
和我一步步部署 kubernetes 叢集
本系列文件介紹使用二進位制部署 kubernetes
叢集的所有步驟,而不是使用 kubeadm
等自動化方式來部署叢集,同時開啟了叢集的TLS安全認證;
在部署的過程中,將詳細列出各元件的啟動引數,給出配置檔案,詳解它們的含義和可能遇到的問題。
部署完成後,你將理解系統各元件的互動原理,進而能快速解決實際問題。
所以本文件主要適合於那些有一定 kubernetes 基礎,想通過一步步部署的方式來學習和了解系統配置、執行原理的人。
專案程式碼中提供了彙總後的markdon和pdf格式的安裝文件,pdf版本文件下載。
注:本文件中不包括docker和私有映象倉庫的安裝。
提供所有的配置檔案
叢集安裝時所有元件用到的配置檔案,包含在以下目錄中:
- etc: service的環境變數配置檔案
- manifest: kubernetes應用的yaml檔案
- systemd :systemd serivce配置檔案
叢集詳情
- Kubernetes 1.6.0
- Docker 1.12.5(使用yum安裝)
- Etcd 3.1.5
- Flanneld 0.7 vxlan 網路
- TLS 認證通訊 (所有元件,如 etcd、kubernetes master 和 node)
- RBAC 授權
- kublet TLS BootStrapping
- kubedns、dashboard、heapster(influxdb、grafana)、EFK(elasticsearch、fluentd、kibana) 叢集外掛
- 私有docker映象倉庫harbor(請自行部署,harbor提供離線安裝包,直接使用docker-compose啟動即可)
步驟介紹
一、建立 kubernetes 各元件 TLS 加密通訊的證書和祕鑰
kubernetes
系統的各元件需要使用 TLS
證書對通訊進行加密,本文件使用 CloudFlare
的 PKI 工具集 cfssl 來生成 Certificate Authority (CA) 和其它證書;
生成的 CA 證書和祕鑰檔案如下:
- ca-key.pem
- ca.pem
- kubernetes-key.pem
- kubernetes.pem
- kube-proxy.pem
- kube-proxy-key.pem
- admin.pem
- admin-key.pem
使用證書的元件如下:
- etcd:使用 ca.pem、kubernetes-key.pem、kubernetes.pem;
- kube-apiserver:使用 ca.pem、kubernetes-key.pem、kubernetes.pem;
- kubelet:使用 ca.pem;
- kube-proxy:使用 ca.pem、kube-proxy-key.pem、kube-proxy.pem;
- kubectl:使用 ca.pem、admin-key.pem、admin.pem;
kube-controller
、kube-scheduler
當前需要和 kube-apiserver
部署在同一臺機器上且使用非安全埠通訊,故不需要證書。
安裝 CFSSL
方式一:直接使用二進位制原始碼包安裝
$ wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 $ chmod +x cfssl_linux-amd64 $ sudo mv cfssl_linux-amd64 /root/local/bin/cfssl $ wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 $ chmod +x cfssljson_linux-amd64 $ sudo mv cfssljson_linux-amd64 /root/local/bin/cfssljson $ wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 $ chmod +x cfssl-certinfo_linux-amd64 $ sudo mv cfssl-certinfo_linux-amd64 /root/local/bin/cfssl-certinfo $ export PATH=/root/local/bin:$PATH
方式二:使用go命令安裝
我們的系統中安裝了Go1.7.5,使用以下命令安裝更快捷:
$go get -u github.com/cloudflare/cfssl/cmd/...
$echo $GOPATH
/usr/local
$ls /usr/local/bin/cfssl*
cfssl cfssl-bundle cfssl-certinfo cfssljson cfssl-newkey cfssl-scan
在$GOPATH/bin
目錄下得到以cfssl開頭的幾個命令。
建立 CA (Certificate Authority)
建立 CA 配置檔案
$ mkdir /root/ssl $ cd /root/ssl $ cfssl print-defaults config > config.json $ cfssl print-defaults csr > csr.json $ cat ca-config.json { "signing": { "default": { "expiry": "8760h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "8760h" } } } }
欄位說明
ca-config.json
:可以定義多個 profiles,分別指定不同的過期時間、使用場景等引數;後續在簽名證書時使用某個 profile;signing
:表示該證書可用於簽名其它證書;生成的 ca.pem 證書中CA=TRUE
;server auth
:表示client可以用該 CA 對server提供的證書進行驗證;client auth
:表示server可以用該CA對client提供的證書進行驗證;
建立 CA 證書籤名請求
$ cat ca-csr.json { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] }
- “CN”:
Common Name
,kube-apiserver 從證書中提取該欄位作為請求的使用者名稱 (User Name);瀏覽器使用該欄位驗證網站是否合法; - “O”:
Organization
,kube-apiserver 從證書中提取該欄位作為請求使用者所屬的組 (Group);
生成 CA 證書和私鑰
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca $ ls ca* ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
建立 kubernetes 證書
建立 kubernetes 證書籤名請求
$ cat kubernetes-csr.json { "CN": "kubernetes", "hosts": [ "127.0.0.1", "172.20.0.112", "172.20.0.113", "172.20.0.114", "172.20.0.115", "10.254.0.1", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] }
- 如果 hosts 欄位不為空則需要指定授權使用該證書的 IP 或域名列表,由於該證書後續被
etcd
叢集和kubernetes master
叢集使用,所以上面分別指定了etcd
叢集、kubernetes master
叢集的主機 IP 和kubernetes
服務的服務 IP(一般是kue-apiserver
指定的service-cluster-ip-range
網段的第一個IP,如 10.254.0.1。
生成 kubernetes 證書和私鑰
$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes $ ls kuberntes* kubernetes.csr kubernetes-csr.json kubernetes-key.pem kubernetes.pem
或者直接在命令列上指定相關引數:
$ echo '{"CN":"kubernetes","hosts":[""],"key":{"algo":"rsa","size":2048}}' | cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes -hostname="127.0.0.1,172.20.0.112,172.20.0.113,172.20.0.114,172.20.0.115,kubernetes,kubernetes.default" - | cfssljson -bare kubernetes
建立 admin 證書
建立 admin 證書籤名請求
$ cat admin-csr.json { "CN": "admin", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "system:masters", "OU": "System" } ] }
- 後續
kube-apiserver
使用RBAC
對客戶端(如kubelet
、kube-proxy
、Pod
)請求進行授權; kube-apiserver
預定義了一些RBAC
使用的RoleBindings
,如cluster-admin
將 Groupsystem:masters
與 Rolecluster-admin
繫結,該 Role 授予了呼叫kube-apiserver
的所有 API的許可權;- OU 指定該證書的 Group 為
system:masters
,kubelet
使用該證書訪問kube-apiserver
時 ,由於證書被 CA 簽名,所以認證通過,同時由於證書使用者組為經過預授權的system:masters
,所以被授予訪問所有 API 的許可權;
生成 admin 證書和私鑰
$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin $ ls admin* admin.csr admin-csr.json admin-key.pem admin.pem
建立 kube-proxy 證書
建立 kube-proxy 證書籤名請求
$ cat kube-proxy-csr.json { "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] }
- CN 指定該證書的 User 為
system:kube-proxy
; kube-apiserver
預定義的 RoleBindingcluster-admin
將Usersystem:kube-proxy
與 Rolesystem:node-proxier
繫結,該 Role 授予了呼叫kube-apiserver
Proxy 相關 API 的許可權;
生成 kube-proxy 客戶端證書和私鑰
$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy $ ls kube-proxy* kube-proxy.csr kube-proxy-csr.json kube-proxy-key.pem kube-proxy.pem
校驗證書
以 kubernetes 證書為例
使用 opsnssl
命令
$ openssl x509 -noout -text -in kubernetes.pem
...
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=Kubernetes
Validity
Not Before: Apr 5 05:36:00 2017 GMT
Not After : Apr 5 05:36:00 2018 GMT
Subject: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=kubernetes
...
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
DD:52:04:43:10:13:A9:29:24:17:3A:0E:D7:14:DB:36:F8:6C:E0:E0
X509v3 Authority Key Identifier:
keyid:44:04:3B:60:BD:69:78:14:68:AF:A0:41:13:F6:17:07:13:63:58:CD
X509v3 Subject Alternative Name:
DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster, DNS:kubernetes.default.svc.cluster.local, IP Address:127.0.0.1, IP Address:172.20.0.112, IP Address:172.20.0.113, IP Address:172.20.0.114, IP Address:172.20.0.115, IP Address:10.254.0.1
...
- 確認
Issuer
欄位的內容和ca-csr.json
一致; - 確認
Subject
欄位的內容和kubernetes-csr.json
一致; - 確認
X509v3 Subject Alternative Name
欄位的內容和kubernetes-csr.json
一致; - 確認
X509v3 Key Usage、Extended Key Usage
欄位的內容和ca-config.json
中kubernetes
profile 一致;
使用 cfssl-certinfo
命令
$ cfssl-certinfo -cert kubernetes.pem ... { "subject": { "common_name": "kubernetes", "country": "CN", "organization": "k8s", "organizational_unit": "System", "locality": "BeiJing", "province": "BeiJing", "names": [ "CN", "BeiJing", "BeiJing", "k8s", "System", "kubernetes" ] }, "issuer": { "common_name": "Kubernetes", "country": "CN", "organization": "k8s", "organizational_unit": "System", "locality": "BeiJing", "province": "BeiJing", "names": [ "CN", "BeiJing", "BeiJing", "k8s", "System", "Kubernetes" ] }, "serial_number": "174360492872423263473151971632292895707129022309", "sans": [ "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local", "127.0.0.1", "10.64.3.7", "10.254.0.1" ], "not_before": "2017-04-05T05:36:00Z", "not_after": "2018-04-05T05:36:00Z", "sigalg": "SHA256WithRSA", ...
分發證書
將生成的證書和祕鑰檔案(字尾名為.pem
)拷貝到所有機器的 /etc/kubernetes/ssl
目錄下備用;
$ sudo mkdir -p /etc/kubernetes/ssl
$ sudo cp *.pem /etc/kubernetes/ssl
參考
二、建立 kubeconfig 檔案
kubelet
、kube-proxy
等 Node 機器上的程序與 Master 機器的 kube-apiserver
程序通訊時需要認證和授權;
kubernetes 1.4 開始支援由 kube-apiserver
為客戶端生成 TLS 證書的 TLS Bootstrapping 功能,這樣就不需要為每個客戶端生成證書了;該功能當前僅支援為 kubelet
生成證書;
建立 TLS Bootstrapping Token
Token auth file
Token可以是任意的包涵128 bit的字串,可以使用安全的隨機數發生器生成。
export BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ') cat > token.csv <<EOF ${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap" EOF
後三行是一句,直接複製上面的指令碼執行即可。
將token.csv發到所有機器(Master 和 Node)的 /etc/kubernetes/
目錄。
$cp token.csv /etc/kubernetes/
建立 kubelet bootstrapping kubeconfig 檔案
$ cd /etc/kubernetes $ export KUBE_APISERVER="https://172.20.0.113:6443" $ # 設定叢集引數 $ kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=bootstrap.kubeconfig $ # 設定客戶端認證引數 $ kubectl config set-credentials kubelet-bootstrap \ --token=${BOOTSTRAP_TOKEN} \ --kubeconfig=bootstrap.kubeconfig $ # 設定上下文引數 $ kubectl config set-context default \ --cluster=kubernetes \ --user=kubelet-bootstrap \ --kubeconfig=bootstrap.kubeconfig $ # 設定預設上下文 $ kubectl config use-context default --kubeconfig=bootstrap.kubeconfig
--embed-certs
為true
時表示將certificate-authority
證書寫入到生成的bootstrap.kubeconfig
檔案中;- 設定客戶端認證引數時沒有指定祕鑰和證書,後續由
kube-apiserver
自動生成;
建立 kube-proxy kubeconfig 檔案
$ export KUBE_APISERVER="https://172.20.0.113:6443" $ # 設定叢集引數 $ kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=kube-proxy.kubeconfig $ # 設定客戶端認證引數 $ kubectl config set-credentials kube-proxy \ --client-certificate=/etc/kubernetes/ssl/kube-proxy.pem \ --client-key=/etc/kubernetes/ssl/kube-proxy-key.pem \ --embed-certs=true \ --kubeconfig=kube-proxy.kubeconfig $ # 設定上下文引數 $ kubectl config set-context default \ --cluster=kubernetes \ --user=kube-proxy \ --kubeconfig=kube-proxy.kubeconfig $ # 設定預設上下文 $ kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
- 設定叢集引數和客戶端認證引數時
--embed-certs
都為true
,這會將certificate-authority
、client-certificate
和client-key
指向的證書檔案內容寫入到生成的kube-proxy.kubeconfig
檔案中; kube-proxy.pem
證書中 CN 為system:kube-proxy
,kube-apiserver
預定義的 RoleBindingcluster-admin
將Usersystem:kube-proxy
與 Rolesystem:node-proxier
繫結,該 Role 授予了呼叫kube-apiserver
Proxy 相關 API 的許可權;
分發 kubeconfig 檔案
將兩個 kubeconfig 檔案分發到所有 Node 機器的 /etc/kubernetes/
目錄
$ cp bootstrap.kubeconfig kube-proxy.kubeconfig /etc/kubernetes/
三、建立高可用 etcd 叢集
kuberntes 系統使用 etcd 儲存所有資料,本文件介紹部署一個三節點高可用 etcd 叢集的步驟,這三個節點複用 kubernetes master 機器,分別命名為sz-pg-oam-docker-test-001.tendcloud.com
、sz-pg-oam-docker-test-002.tendcloud.com
、sz-pg-oam-docker-test-003.tendcloud.com
:
- sz-pg-oam-docker-test-001.tendcloud.com:172.20.0.113
- sz-pg-oam-docker-test-002.tendcloud.com:172.20.0.114
- sz-pg-oam-docker-test-003.tendcloud.com:172.20.0.115
TLS 認證檔案
需要為 etcd 叢集建立加密通訊的 TLS 證書,這裡複用以前建立的 kubernetes 證書
$ cp ca.pem kubernetes-key.pem kubernetes.pem /etc/kubernetes/ssl
- kubernetes 證書的
hosts
欄位列表中包含上面三臺機器的 IP,否則後續證書校驗會失敗;
下載二進位制檔案
到 https://github.com/coreos/etcd/releases
頁面下載最新版本的二進位制檔案
$ https://github.com/coreos/etcd/releases/download/v3.1.5/etcd-v3.1.5-linux-amd64.tar.gz
$ tar -xvf etcd-v3.1.4-linux-amd64.tar.gz
$ sudo mv etcd-v3.1.4-linux-amd64/etcd* /root/local/bin
建立 etcd 的 systemd unit 檔案
注意替換 ETCD_NAME
和 INTERNAL_IP
變數的值;
$ export ETCD_NAME=sz-pg-oam-docker-test-001.tendcloud.com $ export INTERNAL_IP=172.20.0.113 $ sudo mkdir -p /var/lib/etcd /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] Type=notify WorkingDirectory=/var/lib/etcd/ EnvironmentFile=-/etc/etcd/etcd.conf ExecStart=/root/local/bin/etcd \\ --name ${ETCD_NAME} \\ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \\ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\ --peer-cert-file=/etc/kubernetes/ssl/kubernetes.pem \\ --peer-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\ --trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\ --peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\ --initial-advertise-peer-urls https://${INTERNAL_IP}:2380 \\ --listen-peer-urls https://${INTERNAL_IP}:2380 \\ --listen-client-urls https://${INTERNAL_IP}:2379,https://127.0.0.1:2379 \\ --advertise-client-urls https://${INTERNAL_IP}:2379 \\ --initial-cluster-token etcd-cluster-0 \\ --initial-cluster sz-pg-oam-docker-test-001.tendcloud.com=https://172.20.0.113:2380,sz-pg-oam-docker-test-002.tendcloud.com=https://172.20.0.114:2380,sz-pg-oam-docker-test-003.tendcloud.com=https://172.20.0.115:2380 \\ --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
,資料目錄為/var/lib/etcd
,需在啟動服務前建立這兩個目錄; - 為了保證通訊安全,需要指定 etcd 的公私鑰(cert-file和key-file)、Peers 通訊的公私鑰和 CA 證書(peer-cert-file、peer-key-file、peer-trusted-ca-file)、客戶端的CA證書(trusted-ca-file);
- 建立
kubernetes.pem
證書時使用的kubernetes-csr.json
檔案的hosts
欄位包含所有 etcd 節點的 INTERNAL_IP,否則證書校驗會出錯; --initial-cluster-state
值為new
時,--name
的引數值必須位於--initial-cluster
列表中;
啟動 etcd 服務
$ sudo mv etcd.service /etc/systemd/system/
$ sudo systemctl daemon-reload
$ sudo systemctl enable etcd
$ sudo systemctl start etcd
$ systemctl status etcd
在所有的 kubernetes master 節點重複上面的步驟,直到所有機器的 etcd 服務都已啟動。
驗證服務
在任一 kubernetes master 機器上執行如下命令:
$ etcdctl \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ cluster-health 2017-04-11 15:17:09.082250 I | warning: ignoring ServerName for user-provided CA for backwards compatibility is deprecated 2017-04-11 15:17:09.083681 I | warning: ignoring ServerName for user-provided CA for backwards compatibility is deprecated member 9a2ec640d25672e5 is healthy: got healthy result from https://172.20.0.115:2379 member bc6f27ae3be34308 is healthy: got healthy result from https://172.20.0.114:2379 member e5c92ea26c4edba0 is healthy: got healthy result from https://172.20.0.113:2379 cluster is healthy
結果最後一行為 cluster is healthy
時表示叢集服務正常。
三、建立高可用 etcd 叢集
kuberntes 系統使用 etcd 儲存所有資料,本文件介紹部署一個三節點高可用 etcd 叢集的步驟,這三個節點複用 kubernetes master 機器,分別命名為sz-pg-oam-docker-test-001.tendcloud.com
、sz-pg-oam-docker-test-002.tendcloud.com
、sz-pg-oam-docker-test-003.tendcloud.com
:
- sz-pg-oam-docker-test-001.tendcloud.com:172.20.0.113
- sz-pg-oam-docker-test-002.tendcloud.com:172.20.0.114
- sz-pg-oam-docker-test-003.tendcloud.com:172.20.0.115
TLS 認證檔案
需要為 etcd 叢集建立加密通訊的 TLS 證書,這裡複用以前建立的 kubernetes 證書
$ cp ca.pem kubernetes-key.pem kubernetes.pem /etc/kubernetes/ssl
- kubernetes 證書的
hosts
欄位列表中包含上面三臺機器的 IP,否則後續證書校驗會失敗;
下載二進位制檔案
到 https://github.com/coreos/etcd/releases
頁面下載最新版本的二進位制檔案
$ https://github.com/coreos/etcd/releases/download/v3.1.5/etcd-v3.1.5-linux-amd64.tar.gz
$ tar -xvf etcd-v3.1.4-linux-amd64.tar.gz
$ sudo mv etcd-v3.1.4-linux-amd64/etcd* /root/local/bin
建立 etcd 的 systemd unit 檔案
注意替換 ETCD_NAME
和 INTERNAL_IP
變數的值;
$ export ETCD_NAME=sz-pg-oam-docker-test-001.tendcloud.com $ export INTERNAL_IP=172.20.0.113 $ sudo mkdir -p /var/lib/etcd /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] Type=notify WorkingDirectory=/var/lib/etcd/ EnvironmentFile=-/etc/etcd/etcd.conf ExecStart=/root/local/bin/etcd \\ --name ${ETCD_NAME} \\ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \\ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\ --peer-cert-file=/etc/kubernetes/ssl/kubernetes.pem \\ --peer-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\ --trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\ --peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\ --initial-advertise-peer-urls https://${INTERNAL_IP}:2380 \\ --listen-peer-urls https://${INTERNAL_IP}:2380 \\ --listen-client-urls https://${INTERNAL_IP}:2379,https://127.0.0.1:2379 \\ --advertise-client-urls https://${INTERNAL_IP}:2379 \\ --initial-cluster-token etcd-cluster-0 \\ --initial-cluster sz-pg-oam-docker-test-001.tendcloud.com=https://172.20.0.113:2380,sz-pg-oam-docker-test-002.tendcloud.com=https://172.20.0.114:2380,sz-pg-oam-docker-test-003.tendcloud.com=https://172.20.0.115:2380 \\ --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
,資料目錄為/var/lib/etcd
,需在啟動服務前建立這兩個目錄; - 為了保證通訊安全,需要指定 etcd 的公私鑰(cert-file和key-file)、Peers 通訊的公私鑰和 CA 證書(peer-cert-file、peer-key-file、peer-trusted-ca-file)、客戶端的CA證書(trusted-ca-file);
- 建立
kubernetes.pem
證書時使用的kubernetes-csr.json
檔案的hosts
欄位包含所有 etcd 節點的 INTERNAL_IP,否則證書校驗會出錯; --initial-cluster-state
值為new
時,--name
的引數值必須位於--initial-cluster
列表中;
啟動 etcd 服務
$ sudo mv etcd.service /etc/systemd/system/
$ sudo systemctl daemon-reload
$ sudo systemctl enable etcd
$ sudo systemctl start etcd
$ systemctl status etcd
在所有的 kubernetes master 節點重複上面的步驟,直到所有機器的 etcd 服務都已啟動。
驗證服務
在任一 kubernetes master 機器上執行如下命令:
$ etcdctl \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ cluster-health 2017-04-11 15:17:09.082250 I | warning: ignoring ServerName for user-provided CA for backwards compatibility is deprecated 2017-04-11 15:17:09.083681 I | warning: ignoring ServerName for user-provided CA for backwards compatibility is deprecated member 9a2ec640d25672e5 is healthy: got healthy result from https://172.20.0.115:2379 member bc6f27ae3be34308 is healthy: got healthy result from https://172.20.0.114:2379 member e5c92ea26c4edba0 is healthy: got healthy result from https://172.20.0.113:2379 cluster is healthy
結果最後一行為 cluster is healthy
時表示叢集服務正常。
四、下載和配置 kubectl 命令列工具
本文件介紹下載和配置 kubernetes 叢集命令列工具 kubelet 的步驟。
下載 kubectl
$ wget https://dl.k8s.io/v1.6.0/kubernetes-client-linux-amd64.tar.gz $ tar -xzvf kubernetes-client-linux-amd64.tar.gz $ cp kubernetes/client/bin/kube* /usr/bin/ $ chmod a+x /usr/bin/kube*
建立 kubectl kubeconfig 檔案
$ export KUBE_APISERVER="https://172.20.0.113:6443" $ # 設定叢集引數 $ 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
證書 OU 欄位值為system:masters
,kube-apiserver
預定義的 RoleBindingcluster-admin
將 Groupsystem:masters
與 Rolecluster-admin
繫結,該 Role 授予了呼叫kube-apiserver
相關 API 的許可權;- 生成的 kubeconfig 被儲存到
~/.kube/config
檔案;
五、部署高可用 kubernetes master 叢集
kubernetes master 節點包含的元件:
- kube-apiserver
- kube-scheduler
- kube-controller-manager
目前這三個元件需要部署在同一臺機器上。
kube-scheduler
、kube-controller-manager
和kube-apiserver
三者的功能緊密相關;- 同時只能有一個
kube-scheduler
、kube-controller-manager
程序處於工作狀態,如果執行多個,則需要通過選舉產生一個 leader;
本文件記錄部署一個三個節點的高可用 kubernetes master 叢集步驟。(後續建立一個 load balancer 來代理訪問 kube-apiserver 的請求)
TLS 證書檔案
pem和token.csv證書檔案我們在TLS證書和祕鑰這一步中已經建立過了。我們再檢查一下。
$ ls /etc/kubernetes/ssl admin-key.pem admin.pem ca-key.pem ca.pem kube-proxy-key.pem kube-proxy.pem kubernetes-key.pem kubernetes.pem
下載最新版本的二進位制檔案
有兩種下載方式
方式一
從 github release 頁面 下載釋出版 tarball,解壓後再執行下載指令碼
$ wget https://github.com/kubernetes/kubernetes/releases/download/v1.6.0/kubernetes.tar.gz
$ tar -xzvf kubernetes.tar.gz
...
$ cd kubernetes
$ ./cluster/get-kube-binaries.sh
...
方式二
從 CHANGELOG
頁面 下載 client
或 server
tarball 檔案
server
的 tarball kubernetes-server-linux-amd64.tar.gz
已經包含了 client
(kubectl
) 二進位制檔案,所以不用單獨下載kubernetes-client-linux-amd64.tar.gz
檔案;
$ # wget https://dl.k8s.io/v1.6.0/kubernetes-client-linux-amd64.tar.gz $ wget https://dl.k8s.io/v1.6.0/kubernetes-server-linux-amd64.tar.gz $ tar -xzvf kubernetes-server-linux-amd64.tar.gz ... $ cd kubernetes $ tar -xzvf kubernetes-src.tar.gz
將二進位制檔案拷貝到指定路徑
$ cp -r server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kube-proxy,kubelet} /root/local/bin/
配置和啟動 kube-apiserver
建立 kube-apiserver的service配置檔案
serivce配置檔案/usr/lib/systemd/system/kube-apiserver.service
內容:
[Unit] Description=Kubernetes API Service Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=network.target After=etcd.service [Service] EnvironmentFile=-/etc/kubernetes/config EnvironmentFile=-/etc/kubernetes/apiserver ExecStart=/usr/bin/kube-apiserver \ $KUBE_LOGTOSTDERR \ $KUBE_LOG_LEVEL \ $KUBE_ETCD_SERVERS \ $KUBE_API_ADDRESS \ $KUBE_API_PORT \ $KUBELET_PORT \ $KUBE_ALLOW_PRIV \ $KUBE_SERVICE_ADDRESSES \ $KUBE_ADMISSION_CONTROL \ $KUBE_API_ARGS Restart=on-failure Type=notify LimitNOFILE=65536 [Install] WantedBy=multi-user.target
/etc/kubernetes/config
檔案的內容為:
### # kubernetes system config # # The following values are used to configure various aspects of all # kubernetes services, including # # kube-apiserver.service # kube-controller-manager.service # kube-scheduler.service # kubelet.service # kube-proxy.service # logging to stderr means we get it in the systemd journal KUBE_LOGTOSTDERR="--logtostderr=true" # journal message level, 0 is debug KUBE_LOG_LEVEL="--v=0" # Should this cluster be allowed to run privileged docker containers KUBE_ALLOW_PRIV="--allow-privileged=true" # How the controller-manager, scheduler, and proxy find the apiserver #KUBE_MASTER="--master=http://sz-pg-oam-docker-test-001.tendcloud.com:8080" KUBE_MASTER="--master=http://172.20.0.113:8080"
該配置檔案同時被kube-apiserver、kube-controller-manager、kube-scheduler、kubelet、kube-proxy使用。
apiserver配置檔案/etc/kubernetes/apiserver
內容為:
### ## kubernetes system config ## ## The following values are used to configure the kube-apiserver ## # ## The address on the local server to listen to. #KUBE_API_ADDRESS="--insecure-bind-address=sz-pg-oam-docker-test-001.tendcloud.com" KUBE_API_ADDRESS="--advertise-address=172.20.0.113 --bind-address=172.20.0.113 --insecure-bind-address=172.20.0.113" # ## The port on the local server to listen on. #KUBE_API_PORT="--port=8080" # ## Port minions listen on #KUBELET_PORT="--kubelet-port=10250" # ## Comma separated list of nodes in the etcd cluster KUBE_ETCD_SERVERS="--etcd-servers=https://172.20.0.113:2379,172.20.0.114:2379,172.20.0.115:2379" # ## Address range to use for services KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16" # ## default admission control policies KUBE_ADMISSION_CONTROL="--admission-control=ServiceAccount,NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota" # ## Add your own! KUBE_API_ARGS="--authorization-mode=RBAC --runtime-config=rbac.authorization.k8s.io/v1beta1 --kubelet-https=true --experimental-bootstrap-token-auth --token-auth-file=/etc/kubernetes/token.csv --service-node-port-range=30000-32767 --tls-cert-file=/etc/kubernetes/ssl/kubernetes.pem --tls-private-key-file=/etc/kubernetes/ssl/kubernetes-key.pem --client-ca-file=/etc/kubernetes/ssl/ca.pem --service-account-key-file=/etc/kubernetes/ssl/ca-key.pem --etcd-cafile=/etc/kubernetes/ssl/ca.pem --etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem --etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem --enable-swagger-ui=true --apiserver-count=3 --audit-log-maxage=30 --audit-log-maxbackup=3 --audit-log-maxsize=100 --audit-log-path=/var/lib/audit.log --event-ttl=1h"
--authorization-mode=RBAC
指定在安全埠使用 RBAC 授權模式,拒絕未通過授權的請求;- kube-scheduler、kube-controller-manager 一般和 kube-apiserver 部署在同一臺機器上,它們使用非安全埠和 kube-apiserver通訊;
- kubelet、kube-proxy、kubectl 部署在其它 Node 節點上,如果通過安全埠訪問 kube-apiserver,則必須先通過 TLS 證書認證,再通過 RBAC 授權;
- kube-proxy、kubectl 通過在使用的證書裡指定相關的 User、Group 來達到通過 RBAC 授權的目的;
- 如果使用了 kubelet TLS Boostrap 機制,則不能再指定
--kubelet-certificate-authority
、--kubelet-client-certificate
和--kubelet-client-key
選項,否則後續 kube-apiserver 校驗 kubelet 證書時出現 ”x509: certificate signed by unknown authority“ 錯誤; --admission-control
值必須包含ServiceAccount
;--bind-address
不能為127.0.0.1
;runtime-config
配置為rbac.authorization.k8s.io/v1beta1
,表示執行時的apiVersion;--service-cluster-ip-range
指定 Service Cluster IP 地址段,該地址段不能路由可達;- 預設情況下 kubernetes 物件儲存在 etcd
/registry
路徑下,可以通過--etcd-prefix
引數進行調整;
啟動kube-apiserver
$ systemctl daemon-reload
$ systemctl enable kube-apiserver
$ systemctl start kube-apiserver
$ systemctl status kube-apiserver
配置和啟動 kube-controller-manager
建立 kube-controller-manager的serivce配置檔案
檔案路徑/usr/lib/systemd/system/kube-controller-manager.service
Description=Kubernetes Controller Manager Documentation=https://github.com/GoogleCloudPlatform/kubernetes [Service] EnvironmentFile=-/etc/kubernetes/config EnvironmentFile=-/etc/kubernetes/controller-manager ExecStart=/usr/bin/kube-controller-manager \ $KUBE_LOGTOSTDERR \ $KUBE_LOG_LEVEL \ $KUBE_MASTER \ $KUBE_CONTROLLER_MANAGER_ARGS Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target
配置檔案/etc/kubernetes/controller-manager
。
### # The following values are used to configure the kubernetes controller-manager # defaults from config and apiserver should be adequate # Add your own! KUBE_CONTROLLER_MANAGER_ARGS="--address=127.0.0.1 --service-cluster-ip-range=10.254.0.0/16 --cluster-name=kubernetes --cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem --cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem --service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem --root-ca-file=/etc/kubernetes/ssl/ca.pem --leader-elect=true"
--service-cluster-ip-range
引數指定 Cluster 中 Service 的CIDR範圍,該網路在各 Node 間必須路由不可達,必須和 kube-apiserver 中的引數一致;--cluster-signing-*
指定的證書和私鑰檔案用來簽名為 TLS BootStrap 建立的證書和私鑰;--root-ca-file
用來對 kube-apiserver 證書進行校驗,指定該引數後,才會在Pod 容器的 ServiceAccount 中放置該 CA 證書檔案;--address
值必須為127.0.0.1
,因為當前 kube-apiserver 期望 scheduler 和 controller-manager 在同一臺機器,否則:$ kubectl get componentstatuses NAME STATUS MESSAGE ERROR scheduler Unhealthy Get http://127.0.0.1:10251/healthz: dial tcp 127.0.0.1:10251: getsockopt: connection refused controller-manager Healthy ok etcd-2 Unhealthy Get http://172.20.0.113:2379/health: malformed HTTP response "\x15\x03\x01\x00\x02\x02" etcd-0 Healthy {"health": "true"} etcd-1 Healthy {"health": "true"}
啟動 kube-controller-manager
$ systemctl daemon-reload
$ systemctl enable kube-controller-manager
$ systemctl start kube-controller-manager
配置和啟動 kube-scheduler
建立 kube-scheduler的serivce配置檔案
檔案路徑/usr/lib/systemd/system/kube-scheduler.serivce
。
[Unit] Description=Kubernetes Scheduler Plugin Documentation=https://github.com/GoogleCloudPlatform/kubernetes [Service] EnvironmentFile=-/etc/kubernetes/config EnvironmentFile=-/etc/kubernetes/scheduler ExecStart=/usr/bin/kube-scheduler \ $KUBE_LOGTOSTDERR \ $KUBE_LOG_LEVEL \ $KUBE_MASTER \ $KUBE_SCHEDULER_ARGS Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target
配置檔案/etc/kubernetes/scheduler
。
### # kubernetes scheduler config # default config should be adequate # Add your own! KUBE_SCHEDULER_ARGS="--leader-elect=true --address=127.0.0.1"
--address
值必須為127.0.0.1
,因為當前 kube-apiserver 期望 scheduler 和 controller-manager 在同一臺機器;
啟動 kube-scheduler
$ systemctl daemon-reload
$ systemctl enable kube-scheduler
$ systemctl start kube-scheduler
驗證 master 節點功能
$ kubectl get componentstatuses NAME STATUS MESSAGE ERROR scheduler Healthy ok controller-manager Healthy ok etcd-0 Healthy {"health":