使用二進制的方式部署 K8S-1.16 高可用集羣(二十)

1、項目介紹

項目致力於讓有意向使用原生kubernetes集羣的企業或我的,能夠方便的、系統的使用二進制的方式手工搭建kubernetes高可用集羣。而且讓相關的人員能夠更好的理解kubernetes集羣的運做機制。node

軟件版本

  • os centos7.7(ubuntu也適用,須要替換部分命令)
  • kubernetes 1.16.2
  • etcd 3.4.3
  • docker 18.06
  • calico 3.10.1-2
  • coredns

配置策略

kube-apiserver:linux

  • 使用節點本地 nginx 4 層透明代理實現高可用;
  • 關閉非安全端口 8080 和匿名訪問;
  • 在安全端口 6443 接收 https 請求;
  • 嚴格的認證和受權策略 (x50九、token、RBAC);
  • 開啓 bootstrap token 認證,支持 kubelet TLS bootstrapping;
  • 使用 https 訪問 kubelet、etcd,加密通訊;

kube-controller-manager:nginx

  • 3 節點高可用;
  • 關閉非安全端口 10252,在安全端口 10257 接收 https 請求;
  • 使用 kubeconfig 訪問 apiserver 的安全端口;
  • 自動 approve kubelet 證書籤名請求 (CSR),證書過時後自動輪轉;
  • 各 controller 使用本身的 ServiceAccount 訪問 apiserver;

kube-scheduler:git

  • 3 節點高可用;
  • 關閉非安全端口 10251,在安全端口 10259 接收 https 請求;
  • 使用 kubeconfig 訪問 apiserver 的安全端口;

kubelet:github

  • 使用 kubeadm 動態建立 bootstrap token,而不是在 apiserver 中靜態配置;
  • 使用 TLS bootstrap 機制自動生成 client 和 server 證書,過時後自動輪轉;
  • 在 KubeletConfiguration 類型的 JSON 文件配置主要參數;
  • 關閉只讀端口 10255,在安全端口 10250 接收 https 請求,對請求進行認證和受權,拒絕匿名訪問和非受權訪問;
  • 使用 kubeconfig 訪問 apiserver 的安全端口;

kube-proxy:web

  • 使用 kubeconfig 訪問 apiserver 的安全端口;
  • 在 KubeProxyConfiguration 類型的 JSON 文件配置主要參數;
  • 使用 ipvs 代理模式;

集羣插件:docker

  • DNS:使用功能、性能更好的 coredns;
  • Dashboard:支持登陸認證;
  • Metric:metrics-server,使用 https 訪問 kubelet 安全端口;
  • Log:Elasticsearch、Fluend、Kibana;
  • Registry 鏡像庫:docker-registry、harbor;

2、實踐環境準備

1. 服務器說明

咱們這裏使用的是五臺centos 7.7虛擬機,具體信息以下表:json

系統類型 IP地址 節點角色 CPU Memory Hostname
centos-7.7 172.18.0.100 master >=2 >=2G k8s-m01
centos-7.7 172.18.0.101 master >=2 >=2G k8s-m02
centos-7.7 172.18.0.102 master >=2 >=2G k8s-m03
centos-7.7 172.18.0.103 worker >=2 >=2G k8s-n01
centos-7.7 172.18.0.104 worker >=2 >=2G k8s-n02

使用二進制的方式部署 K8S-1.16 高可用集羣(二十)

2. 系統設置(全部節點)

2.1 主機名

主機名必須每一個節點都不同,而且保證全部點之間能夠經過 hostname 互相訪問。bootstrap

# 查看主機名
$ hostname

# 修改主機名
$ hostnamectl set-hostname <your_hostname>

# 配置host,使主節點之間能夠經過hostname互相訪問
$ vi /etc/hosts
# <node-ip> <node-hostname>

2.2 安裝依賴包

# 更新yum
$ yum update

# 安裝依賴包
$ yum install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp wget

## 時間同步
$ ntpdate time1.aliyun.com

2.3 關閉防火牆、swap,重置iptables

# 關閉防火牆
$ systemctl stop firewalld && systemctl disable firewalld

# 重置iptables
$ iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && iptables -P FORWARD ACCEPT

# 關閉swap
$ swapoff -a
$ sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab

# 關閉selinux
$ setenforce 0

# 關閉dnsmasq(不然可能致使docker容器沒法解析域名)
$ service dnsmasq stop && systemctl disable dnsmasq

2.4 系統參數設置

# 製做配置文件
$ cat > /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
vm.swappiness=0
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
EOF

# 生效文件
$ sysctl -p /etc/sysctl.d/kubernetes.conf

2.5 加載內核模塊

modprobe ip_vs_rr
modprobe br_netfilter

3. 安裝docker(worker節點)

根據kubernetes對docker版本的兼容測試狀況,咱們選擇18.06版本,咱們配置阿里雲的源,速度比較快。ubuntu

# 添加 yum 源
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -P /etc/yum.repos.d/

# 清理原有版本
yum remove -y docker* container-selinux

# 安裝docker
yum list docker-ce.x86_64  --showduplicates |sort -r
yum install docker-ce-18.06.1.ce -y

# 開機啓動
systemctl enable docker

# 配置加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://hdi5v8p1.mirror.aliyuncs.com"]
}
EOF

# 啓動docker服務
service docker restart

4. 準備二進制文件(全部節點)

4.1 配置免密登陸

爲了方便文件的copy咱們選擇一箇中轉節點(隨便一個節點,能夠是集羣中的也能夠是非集羣中的),配置好跟其餘全部節點的免密登陸,咱們這裏使用 k8s-m01。

# 看看是否已經存在rsa公鑰
$ cat ~/.ssh/id_rsa.pub

# 若是不存在就建立一個新的
$ ssh-keygen -t rsa

# 免密鑰認證
$ ssh-copy-id root@<your-server-ip>

4.2 下載二進制文件

官方下載地址(在CHANGELOG連接裏面):
https://github.com/kubernetes/kubernetes/releases

咱們選擇的版本是 1.16.2

網盤下載地址--推薦(我從官網下載整理好的文件):
連接: https://pan.baidu.com/s/1Ut9VERgm55B4lmz0wjjzFQ
提取碼: mjem

4.3 分發文件

# 把文件copy到每一個節點上(注意替換本身的文件目錄)
$ scp master/* <user>@<master-ip>:/usr/local/bin/
$ scp worker/* <user>@<worker-ip>:/usr/local/bin/

# 給文件添加可執行權限
$ chmod +x /usr/local/bin/*

5. 準備配置文件(k8s-m01 節點)

上一步咱們下載了kubernetes各個組件的二進制文件,這些可執行文件的運行也是須要添加不少參數的,包括有的還會依賴一些配置文件。如今咱們就把運行它們須要的參數和配置文件都準備好。

5.1 下載配置文件

我這準備了一個項目,專門爲你們按照本身的環境生成配置的。它只是幫助你們儘可能的減小了機械化的重複工做。它並不會幫你設置系統環境,不會給你安裝軟件。總之就是會減小你的部署工做量,但不會耽誤你對整個系統的認識和把控。

$ cd ~
$ git clone https://github.com/wangzan18/kubernetes-ha-binary.git

# 看看git內容
$ ls -l kubernetes-ha-binary
addons/
configs/
pki/
services/
init.sh
global-configs.properties

5.2 文件說明

addons :kubernetes的插件目錄,包括calico、coredns、dashboard等。

configs:這個目錄比較 - 凌亂,包含了部署集羣過程當中用到的雜七雜八的配置文件、腳本文件等。

pki:各個組件的認證受權相關證書配置。

services:全部的kubernetes服務(service)配置文件。

global-configs.properties:全局配置,包含各類易變的配置內容。

init.sh:初始化腳本,配置好global-config以後,會自動生成全部配置文件。

5.3 生成配置

這裏會根據你們各自的環境生成kubernetes部署過程須要的配置文件。
在每一個節點上都生成一遍,把全部配置都生成好,後面會根據節點類型去使用相關的配置。

# cd到以前下載的git代碼目錄
$ cd kubernetes-ha-binary

# 編輯屬性配置(根據文件註釋中的說明填寫好每一個key-value)
$ vim global-config.properties

# 生成配置文件,確保執行過程沒有異常信息
$ ./init.sh

# 查看生成的配置文件,確保腳本執行成功
$ find target/ -type f

3、高可用集羣部署

1. CA證書(任意節點)

1.1 安裝cfssl

cfssl是很是好用的CA工具,咱們用它來生成證書和祕鑰文件
安裝過程比較簡單,以下:

# 下載
$ wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl
$ wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson

# 修改成可執行權限
$ chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson

# 驗證
$ cfssl version
Version: 1.2.0
Revision: dev
Runtime: go1.6

1.2 生成根證書

查看證書配置文件,CA 配置文件用於配置根證書的使用場景 (profile) 和具體參數 (usage,過時時間、服務端認證、客戶端認證、加密等),後續在簽名其它證書時須要指定特定場景。

$ cd target/pki/
$ cat ca-config.json
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}
  • signing:表示該證書可用於簽名其它證書,生成的 ca.pem 證書中 CA=TRUE
  • server auth:表示 client 能夠用該該證書對 server 提供的證書進行驗證;
  • client auth:表示 server 能夠用該該證書對 client 提供的證書進行驗證;

查看證書籤名請求文件。

$ cat ca-csr.json 
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "seven"
    }
  ]
}
  • CN:Common Name,kube-apiserver 從證書中提取該字段做爲請求的用戶名 (User Name),瀏覽器使用該字段驗證網站是否合法;
  • O:Organization,kube-apiserver 從證書中提取該字段做爲請求用戶所屬的組 (Group)
  • kube-apiserver 將提取的 User、Group 做爲 RBAC 受權的用戶標識;

根證書是集羣全部節點共享的,只須要建立一個 CA 證書,後續建立的全部證書都由它簽名。

# 生成證書和私鑰
$ cd target/pki
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca

# 生成完成後會有如下文件(咱們最終想要的就是ca-key.pem和ca.pem,一個祕鑰,一個證書)
$ ls
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem

# 建立目錄
$ ssh <user>@<node-ip> "mkdir -p /etc/kubernetes/pki/"

# 分發到每一個matser主節點
$ scp ca*.pem <user>@<master-ip>:/etc/kubernetes/pki/

2. 部署etcd集羣(master節點)

2.1 下載etcd,並傳到各master節點

$ wget https://github.com/etcd-io/etcd/releases/download/v3.4.3/etcd-v3.4.3-linux-amd64.tar.gz
$ tar xf etcd-v3.4.3-linux-amd64.tar.gz
$ scp etcd-v3.4.3-linux-amd64/etcd* <user>@<master-ip>:/usr/local/bin/

2.2 生成證書和私鑰

查看證書請求文件。

$ cd target/pki/etcd
$ cat etcd-csr.json
{
  "CN": "etcd",
  "hosts": [
    "127.0.0.1",
    "172.18.0.100",
    "172.18.0.101",
    "172.18.0.102"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "seven"
    }
  ]
}
  • hosts 字段指定受權使用該證書的 etcd 節點 IP 或域名列表,須要將 etcd 集羣的三個節點 IP 都列在其中;
# 生成證書、私鑰
$ cfssl gencert -ca=../ca.pem \
    -ca-key=../ca-key.pem \
    -config=../ca-config.json \
    -profile=kubernetes etcd-csr.json | cfssljson -bare etcd

# 分發到每一個etcd節點(master節點)
$ scp etcd*.pem <user>@<master-ip>:/etc/kubernetes/pki/

2.3 建立service文件

# scp配置文件到每一個master節點
$ scp target/<node-ip>/services/etcd.service <node-ip>:/etc/systemd/system/

# 建立數據和工做目錄
$ ssh <user>@<node-ip> "mkdir -p /var/lib/etcd"

2.4 啓動服務

etcd 進程首次啓動時會等待其它節點的 etcd 加入集羣,命令 systemctl start etcd 會卡住一段時間,爲正常現象。

#啓動服務
$ systemctl daemon-reload && systemctl enable etcd && systemctl restart etcd

#查看狀態
$ service etcd status

#查看啓動日誌
$ journalctl -f -u etcd

#查看服務監聽端口
$ netstat -tlnp |grep etcd

3. 部署api-server(master節點)

3.1 生成證書和私鑰

查看證書請求文件。

$ cd target/pki/apiserver
$ cat kubernetes-csr.json 
{
  "CN": "kubernetes",
  "hosts": [
    "127.0.0.1",
    "172.18.0.100",
    "172.18.0.101",
    "172.18.0.102",
    "172.18.0.88",
    "10.96.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": "seven"
    }
  ]
}
# 生成證書、私鑰
$ cfssl gencert -ca=../ca.pem \
  -ca-key=../ca-key.pem \
  -config=../ca-config.json \
  -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes

# 分發到每一個master節點
$ scp kubernetes*.pem <user>@<master-ip>:/etc/kubernetes/pki/

3.2 建立後續訪問 metrics-server 使用的證書

建立證書籤名請求:

$ cd target/pki/metrics-server
$ cat > proxy-client-csr.json <<EOF
{
  "CN": "aggregator",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "seven"
    }
  ]
}
EOF
  • CN 名稱須要位於 kube-apiserver 的 --requestheader-allowed-names 參數中,不然後續訪問 metrics 時會提示權限不足。

生成證書和私鑰:

$ cfssl gencert -ca=../ca.pem \
  -ca-key=../ca-key.pem  \
  -config=../ca-config.json  \
  -profile=kubernetes proxy-client-csr.json | cfssljson -bare proxy-client

# 分發到每一個master節點
$ scp proxy-client*.pem <user>@<master-ip>:/etc/kubernetes/pki/

3.3 建立service文件

# scp配置文件到每一個master節點
$ scp target/<node-ip>/services/kube-apiserver.service <user>@<node-ip>:/etc/systemd/system/

# 建立日誌目錄
$ ssh <user>@<node-ip> "mkdir -p /var/log/kubernetes"

# 複製配置文件
$ scp target/configs/encryption-config.yaml <user>@<master-ip>:/etc/kubernetes/
$ scp target/configs/audit-policy.yaml <user>@<master-ip>:/etc/kubernetes/

3.3 啓動服務

#啓動服務
$ systemctl daemon-reload && systemctl enable kube-apiserver && systemctl restart kube-apiserver

#查看運行狀態
$ service kube-apiserver status

#查看日誌
$ journalctl -f -u kube-apiserver

#檢查監聽端口
$ netstat -ntlp|grep kube-apiserver

4. 部署keepalived - apiserver高可用(master節點)

可使用 nginx 作負載均衡器,把請求分發到後面三臺apiserver服務器上面,這樣最好,也是官方推薦的。

4.1 安裝keepalived

# 在兩個主節點上安裝keepalived(一主一備),我這裏選擇 k8s-m01, k8s-m02
$ yum install -y keepalived

4.2 建立keepalived配置文件

# 建立目錄
$ ssh <user>@<master-ip> "mkdir -p /etc/keepalived"
$ ssh <user>@<backup-ip> "mkdir -p /etc/keepalived"

# 分發配置文件
$ scp target/configs/keepalived-master.conf <user>@<master-ip>:/etc/keepalived/keepalived.conf
$ scp target/configs/keepalived-backup.conf <user>@<backup-ip>:/etc/keepalived/keepalived.conf

# 分發監測腳本
$ scp target/configs/check-apiserver.sh <user>@<master-ip>:/etc/keepalived/
$ scp target/configs/check-apiserver.sh <user>@<backup-ip>:/etc/keepalived/

4.3 啓動keepalived

# 分別在master和backup上啓動服務
$ systemctl enable keepalived && service keepalived start

# 檢查狀態
$ service keepalived status

# 查看日誌
$ journalctl -f -u keepalived

# 訪問測試
$ curl --insecure https://<master-vip>:6443/
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {

  },
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}

5. 部署kubectl(任意節點),我選擇 k8s-m01

kubectl 是 kubernetes 集羣的命令行管理工具,它默認從 ~/.kube/config 文件讀取 kube-apiserver 地址、證書、用戶名等信息。

5.1 建立 admin 證書和私鑰

kubectl 與 apiserver https 安全端口通訊,apiserver 對提供的證書進行認證和受權。

kubectl 做爲集羣的管理工具,須要被授予最高權限。這裏建立具備最高權限的 admin 證書。

$ cd target/pki/admin
$ cat admin-csr.json 
{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "system:masters",
      "OU": "seven"
    }
  ]
}
  • O 爲 system:masters,kube-apiserver 收到該證書後將請求的 Group 設置爲 system:masters;
  • 預約義的 ClusterRoleBinding cluster-admin 將 Group system:masters 與 Role cluster-admin 綁定,該 Role 授予全部 API的權限;
  • 該證書只會被 kubectl 當作 client 證書使用,因此 hosts 字段爲空;
# 建立證書、私鑰
$ cfssl gencert -ca=../ca.pem \
  -ca-key=../ca-key.pem \
  -config=../ca-config.json \
  -profile=kubernetes admin-csr.json | cfssljson -bare admin

5.2 建立kubeconfig配置文件

kubeconfig 爲 kubectl 的配置文件,包含訪問 apiserver 的全部信息,如 apiserver 地址、CA 證書和自身使用的證書

# 設置集羣參數
$ kubectl config set-cluster kubernetes \
  --certificate-authority=../ca.pem \
  --embed-certs=true \
  --server=https://<MASTER_VIP>:6443 \
  --kubeconfig=kube.config

# 設置客戶端認證參數
$ kubectl config set-credentials admin \
  --client-certificate=admin.pem \
  --client-key=admin-key.pem \
  --embed-certs=true \
  --kubeconfig=kube.config

# 設置上下文參數
$ kubectl config set-context admin@kubernetes \
  --cluster=kubernetes \
  --user=admin \
  --kubeconfig=kube.config

# 設置默認上下文
$ kubectl config use-context admin@kubernetes --kubeconfig=kube.config

# 分發到目標節點
$ scp kube.config <user>@<node-ip>:~/.kube/config
  • --certificate-authority:驗證 kube-apiserver 證書的根證書;
  • --client-certificate--client-key:剛生成的 admin 證書和私鑰,鏈接 kube-apiserver 時使用;
  • --embed-certs=true:將 ca.pem 和 admin.pem 證書內容嵌入到生成的 kubectl.kubeconfig 文件中(不加時,寫入的是證書文件路徑,後續拷貝 kubeconfig 到其它機器時,還須要單獨拷貝證書文件,不方便。);

5.3 授予 kubernetes 證書訪問 kubelet API 的權限

在執行 kubectl exec、run、logs 等命令時,apiserver 會轉發到 kubelet。這裏定義 RBAC 規則,受權 apiserver 調用 kubelet API。

$ kubectl create clusterrolebinding kube-apiserver:kubelet-apis --clusterrole=system:kubelet-api-admin --user kubernetes

5.4 小測試

# 查看集羣信息
$ kubectl cluster-info
$ kubectl get all -A
$ kubectl get cs

6. 部署controller-manager(master節點)

controller-manager啓動後將經過競爭選舉機制產生一個 leader 節點,其它節點爲阻塞狀態。當 leader 節點不可用後,剩餘節點將再次進行選舉產生新的 leader 節點,從而保證服務的可用性。

6.1 建立證書和私鑰

查看證書請求。

$ cd target/pki/controller-manager
$ cat controller-manager-csr.json 
{
    "CN": "system:kube-controller-manager",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "hosts": [
      "127.0.0.1",
      "172.18.0.100",
      "172.18.0.101",
      "172.18.0.102"
    ],
    "names": [
      {
        "C": "CN",
        "ST": "BeiJing",
        "L": "BeiJing",
        "O": "system:kube-controller-manager",
        "OU": "seven"
      }
    ]
}
  • hosts 列表包含全部 kube-controller-manager 節點 IP;
  • CN 和 O 均爲 system:kube-controller-manager,kubernetes 內置的 ClusterRoleBindings system:kube-controller-manager 賦予 kube-controller-manager 工做所需的權限。
# 生成證書、私鑰
$ cfssl gencert -ca=../ca.pem \
  -ca-key=../ca-key.pem \
  -config=../ca-config.json \
  -profile=kubernetes controller-manager-csr.json | cfssljson -bare controller-manager

# 分發到每一個master節點
$ scp controller-manager*.pem <user>@<node-ip>:/etc/kubernetes/pki/

6.2 建立controller-manager的kubeconfig

# 建立kubeconfig
$ kubectl config set-cluster kubernetes \
  --certificate-authority=../ca.pem \
  --embed-certs=true \
  --server=https://<MASTER_VIP>:6443 \
  --kubeconfig=controller-manager.kubeconfig

$ kubectl config set-credentials system:kube-controller-manager \
  --client-certificate=controller-manager.pem \
  --client-key=controller-manager-key.pem \
  --embed-certs=true \
  --kubeconfig=controller-manager.kubeconfig

$ kubectl config set-context system:kube-controller-manager@kubernetes \
  --cluster=kubernetes \
  --user=system:kube-controller-manager \
  --kubeconfig=controller-manager.kubeconfig

$ kubectl config use-context system:kube-controller-manager@kubernetes --kubeconfig=controller-manager.kubeconfig

# 分發controller-manager.kubeconfig
$ scp controller-manager.kubeconfig <user>@<node-ip>:/etc/kubernetes/

6.3 建立service文件

# scp配置文件到每一個master節點
$ scp target/<node-ip>/services/kube-controller-manager.service <user>@<node-ip>:/etc/systemd/system/

6.4 啓動服務

# 啓動服務
$ systemctl daemon-reload && systemctl enable kube-controller-manager && systemctl restart kube-controller-manager

# 檢查狀態
$ service kube-controller-manager status

# 查看日誌
$ journalctl -f -u kube-controller-manager

# 查看leader
$ kubectl get endpoints kube-controller-manager --namespace=kube-system -o yaml

7. 部署scheduler(master節點)

scheduler啓動後將經過競爭選舉機制產生一個 leader 節點,其它節點爲阻塞狀態。當 leader 節點不可用後,剩餘節點將再次進行選舉產生新的 leader 節點,從而保證服務的可用性。

7.1 建立證書和私鑰

查看證書請求文件。

$ cd target/pki/scheduler
$ cat scheduler-csr.json 
{
    "CN": "system:kube-scheduler",
    "hosts": [
      "127.0.0.1",
      "172.18.0.100",
      "172.18.0.101",
      "172.18.0.102"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
      {
        "C": "CN",
        "ST": "BeiJing",
        "L": "BeiJing",
        "O": "system:kube-scheduler",
        "OU": "seven"
      }
    ]
}
  • hosts 列表包含全部 kube-scheduler 節點 IP;
  • CN 和 O 均爲 system:kube-scheduler,kubernetes 內置的 ClusterRoleBindings system:kube-scheduler 將賦予 kube-scheduler 工做所需的權限;
# 生成證書、私鑰
$ cfssl gencert -ca=../ca.pem \
  -ca-key=../ca-key.pem \
  -config=../ca-config.json \
  -profile=kubernetes scheduler-csr.json | cfssljson -bare kube-scheduler

# 分發到每一個master節點
$ scp kube-scheduler*.pem <user>@<node-ip>:/etc/kubernetes/pki/

7.2 建立scheduler的kubeconfig

# 建立kubeconfig
$ kubectl config set-cluster kubernetes \
  --certificate-authority=../ca.pem \
  --embed-certs=true \
  --server=https://<MASTER_VIP>:6443 \
  --kubeconfig=kube-scheduler.kubeconfig

$ kubectl config set-credentials system:kube-scheduler \
  --client-certificate=kube-scheduler.pem \
  --client-key=kube-scheduler-key.pem \
  --embed-certs=true \
  --kubeconfig=kube-scheduler.kubeconfig

$ kubectl config set-context system:kube-scheduler@kubernetes \
  --cluster=kubernetes \
  --user=system:kube-scheduler \
  --kubeconfig=kube-scheduler.kubeconfig

$ kubectl config use-context system:kube-scheduler@kubernetes --kubeconfig=kube-scheduler.kubeconfig

# 分發kubeconfig
$ scp kube-scheduler.kubeconfig <user>@<node-ip>:/etc/kubernetes/

7.3 建立service文件

# scp配置文件到每一個master節點
$ scp target/<node-ip>/services/kube-scheduler.service <user>@<node-ip>:/etc/systemd/system/
$ scp target/<node-ip>/configs/kube-scheduler.config.yaml <user>@<node-ip>:/etc/kubernetes/

7.4 啓動服務

# 啓動服務
$ systemctl daemon-reload && systemctl enable kube-scheduler && systemctl restart kube-scheduler

# 檢查狀態
$ service kube-scheduler status

# 查看日誌
$ journalctl -f -u kube-scheduler

# 查看leader
$ kubectl get endpoints kube-scheduler --namespace=kube-system -o yaml

8. 部署kubelet(worker節點)

8.1 建立bootstrap配置文件

# 建立 token
$ cd target/pki/admin
$ export BOOTSTRAP_TOKEN=$(kubeadm token create \
      --description kubelet-bootstrap-token \
      --groups system:bootstrappers:worker \
      --kubeconfig kube.config)

# 設置集羣參數
$ kubectl config set-cluster kubernetes \
      --certificate-authority=../ca.pem \
      --embed-certs=true \
      --server=https://<MASTER_VIP>:6443 \
      --kubeconfig=kubelet-bootstrap.kubeconfig

# 設置客戶端認證參數
$ kubectl config set-credentials kubelet-bootstrap \
      --token=${BOOTSTRAP_TOKEN} \
      --kubeconfig=kubelet-bootstrap.kubeconfig

# 設置上下文參數
$ kubectl config set-context kubelet@kubernetes \
      --cluster=kubernetes \
      --user=kubelet-bootstrap \
      --kubeconfig=kubelet-bootstrap.kubeconfig

# 設置默認上下文
$ kubectl config use-context kubelet@kubernetes --kubeconfig=kubelet-bootstrap.kubeconfig

# 把生成的配置copy到每一個worker節點上
$ scp kubelet-bootstrap.kubeconfig <user>@<node-ip>:/etc/kubernetes/kubelet-bootstrap.kubeconfig

# 把ca分發到每一個worker節點
$ scp target/pki/ca.pem <user>@<node-ip>:/etc/kubernetes/pki/

# 查看生成的 token
$ kubeadm token list --kubeconfig ~/.kube/config
  • 向 kubeconfig 寫入的是 token,bootstrap 結束後 kube-controller-manager 爲 kubelet 建立 client 和 server 證書;
  • token 有效期爲 1 天,超期後將不能再被用來 boostrap kubelet,且會被 kube-controller-manager 的 tokencleaner 清理;
  • kube-apiserver 接收 kubelet 的 bootstrap token 後,將請求的 user 設置爲 system:bootstrap:&lt;Token ID&gt;,group 設置爲 system:bootstrappers,後續將爲這個 group 設置 ClusterRoleBinding;

8.2 kubelet配置文件

把kubelet配置文件分發到每一個worker節點上

$ scp target/worker-<node-ip>/kubelet.config.json <user>@<node-ip>:/etc/kubernetes/
cat kubelet.config.json 
{
  "kind": "KubeletConfiguration",
  "apiVersion": "kubelet.config.k8s.io/v1beta1",
  "authentication": {
    "x509": {
      "clientCAFile": "/etc/kubernetes/pki/ca.pem"
    },
    "webhook": {
      "enabled": true,
      "cacheTTL": "2m0s"
    },
    "anonymous": {
      "enabled": false
    }
  },
  "authorization": {
    "mode": "Webhook",
    "webhook": {
      "cacheAuthorizedTTL": "5m0s",
      "cacheUnauthorizedTTL": "30s"
    }
  },
  "address": "172.18.0.103",
  "staticPodPath": "",
  "port": 10250,
  "readOnlyPort": 10255,
  "cgroupDriver": "cgroupfs",
  "hairpinMode": "promiscuous-bridge",
  "serializeImagePulls": false,
  "featureGates": {
    "RotateKubeletClientCertificate": true,
    "RotateKubeletServerCertificate": true
  },
  "clusterDomain": "cluster.local.",
  "clusterDNS": ["10.96.0.2"]
}
  • authentication.anonymous.enabled:設置爲 false,不容許匿名訪問 10250 端口;
  • authentication.x509.clientCAFile:指定簽名客戶端證書的 CA 證書,開啓 HTTPs 證書認證;
  • authentication.webhook.enabled=true:開啓 HTTPs bearer token 認證;

同時配置了以下受權參數:

  • authroization.mode=Webhook:開啓 RBAC 受權;

kubelet 收到請求後,使用 clientCAFile 對證書籤名進行認證,或者查詢 bearer token 是否有效。若是二者都沒經過,則拒絕請求,提示 Unauthorized:

8.3 kubelet服務文件

把kubelet服務文件分發到每一個worker節點上

$ scp target/worker-<node-ip>/kubelet.service <user>@<node-ip>:/etc/systemd/system/

8.4 啓動服務

kublet 啓動時查找配置的 --kubeletconfig 文件是否存在,若是不存在則使用 --bootstrap-kubeconfig 向 kube-apiserver 發送證書籤名請求 (CSR)。
kube-apiserver 收到 CSR 請求後,對其中的 Token 進行認證(事先使用 kubeadm 建立的 token),認證經過後將請求的 user 設置爲 system:bootstrap:,group 設置爲 system:bootstrappers,這就是Bootstrap Token Auth。

# bootstrap附權
$ kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers

# 啓動服務
$ mkdir -p /var/lib/kubelet
$ mkdir -p /var/log/kubernetes
$ systemctl daemon-reload && systemctl enable kubelet && systemctl restart kubelet

# 在master上Approve bootstrap請求
$ kubectl get csr
$ kubectl certificate approve <name> 

# 查看服務狀態
$ service kubelet status

# 查看日誌
$ journalctl -f -u kubelet
  • kubelet 啓動後使用 --bootstrap-kubeconfig 向 kube-apiserver 發送 CSR 請求,當這個 CSR 被 approve 後,kube-controller-manager 爲 kubelet 建立 TLS 客戶端證書、私鑰和 --kubeletconfig 文件。
  • 注意:kube-controller-manager 須要配置 --cluster-signing-cert-file 和 --cluster-signing-key-file 參數,纔會爲 TLS Bootstrap 建立證書和私鑰。

9. 部署kube-proxy(worker節點)

9.1 建立證書和私鑰

查看證書請求文件。

$ cd target/pki/proxy
cat kube-proxy-csr.json 
{
  "CN": "system:kube-proxy",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "seven"
    }
  ]
}
  • CN:指定該證書的 User 爲 system:kube-proxy
  • 預約義的 RoleBinding system:node-proxier 將User system:kube-proxy 與 Role system:node-proxier 綁定,該 Role 授予了調用 kube-apiserver Proxy 相關 API 的權限;
  • 該證書只會被 kube-proxy 當作 client 證書使用,因此 hosts 字段爲空;
$ cfssl gencert -ca=../ca.pem \
  -ca-key=../ca-key.pem \
  -config=../ca-config.json \
  -profile=kubernetes  kube-proxy-csr.json | cfssljson -bare kube-proxy

9.2 建立和分發 kubeconfig 文件

# 建立kube-proxy.kubeconfig
$ kubectl config set-cluster kubernetes \
  --certificate-authority=../ca.pem \
  --embed-certs=true \
  --server=https://<master-vip>:6443 \
  --kubeconfig=kube-proxy.kubeconfig

$ kubectl config set-credentials kube-proxy \
  --client-certificate=kube-proxy.pem \
  --client-key=kube-proxy-key.pem \
  --embed-certs=true \
  --kubeconfig=kube-proxy.kubeconfig

$ kubectl config set-context kube-proxy@kubernetes \
  --cluster=kubernetes \
  --user=kube-proxy \
  --kubeconfig=kube-proxy.kubeconfig

$ kubectl config use-context kube-proxy@kubernetes --kubeconfig=kube-proxy.kubeconfig

# 分發kube-proxy.kubeconfig 到 node 節點
$ scp kube-proxy.kubeconfig <user>@<node-ip>:/etc/kubernetes/

9.3 分發kube-proxy.config

$ scp target/worker-<node-ip>/kube-proxy.config.yaml <user>@<node-ip>:/etc/kubernetes/

9.4 分發kube-proxy服務文件

$ scp target/services/kube-proxy.service <user>@<node-ip>:/etc/systemd/system/

9.5 啓動服務

# 建立依賴目錄
$ mkdir -p /var/lib/kube-proxy

# 啓動服務
$ systemctl daemon-reload && systemctl enable kube-proxy && systemctl restart kube-proxy

# 查看狀態
$ service kube-proxy status

# 查看日誌
$ journalctl -f -u kube-proxy

目前是 iptables 模式,使用 ipvs 模式能夠修改文件 kube-proxy.config.yaml
我這裏遇到的一個問題是 iptables 版本太低,若是遇到,能夠編譯安裝使用新版本。

10. 部署CNI插件 - calico

咱們使用calico官方的安裝方式來部署。

# 建立目錄(在配置了kubectl的節點上執行)
$ mkdir -p /etc/kubernetes/addons

# 上傳calico配置到配置好kubectl的節點(一個節點便可)
$ scp target/addons/calico.yaml <user>@<node-ip>:/etc/kubernetes/addons/

# 部署calico
$ kubectl apply -f /etc/kubernetes/addons/calico.yaml

# 查看狀態
$ kubectl get pods -n kube-system

https://docs.projectcalico.org/v3.10/getting-started/kubernetes/

11. 部署DNS插件 - coredns

# 上傳配置文件
$ scp target/addons/coredns.yaml <user>@<node-ip>:/etc/kubernetes/addons/

# 部署coredns
$ kubectl apply -f /etc/kubernetes/addons/coredns.yaml

https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base

4、集羣可用性測試

1. 建立nginx ds

# 寫入配置
$ cat > nginx-ds.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: nginx-ds
  labels:
    app: nginx-ds
spec:
  type: NodePort
  selector:
    app: nginx-ds
  ports:
  - name: http
    port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-ds
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
spec:
  template:
    metadata:
      labels:
        app: nginx-ds
    spec:
      containers:
      - name: my-nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
  selector:
    matchLabels:
      app: nginx-ds
EOF

# 建立ds
$ kubectl apply -f nginx-ds.yml

2. 檢查各類ip連通性

# 檢查各 Node 上的 Pod IP 連通性(主節點沒有calico因此不能訪問podip)
$ kubectl get pods -o wide

# 在每一個worker節點上ping pod ip
$ ping <pod-ip>

# 檢查service可達性
$ kubectl get svc

# 在每一個worker節點上訪問服務(主節點沒有proxy因此不能訪問service-ip)
$ curl <service-ip>:<port>

# 在每一個節點檢查node-port可用性
$ curl <node-ip>:<port>

3. 檢查dns可用性

# 建立一個nginx pod
$ cat > pod-nginx.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.7.9
    ports:
    - containerPort: 80
EOF

# 建立pod
$ kubectl apply -f pod-nginx.yaml

# 進入pod,查看dns
$ kubectl exec nginx -it -- /bin/bash

# 查看dns配置
root@nginx:/# cat /etc/resolv.conf

# 查看名字是否能夠正確解析
root@nginx:/# ping nginx-ds
root@nginx:/# ping kubernetes

五. 部署dashboard

1. 部署dashboard

# 上傳dashboard配置
$ scp target/addons/dashboard-all.yaml <user>@<node-ip>:/etc/kubernetes/addons/

# 建立服務
$ kubectl apply -f /etc/kubernetes/addons/dashboard-all.yaml

# 查看服務運行狀況
$ kubectl get deployment kubernetes-dashboard -n kube-system
$ kubectl --namespace kube-system get pods -o wide
$ kubectl get services kubernetes-dashboard -n kube-system
$ netstat -ntlp|grep 8401

2. 訪問dashboard

爲了集羣安全,從 1.7 開始,dashboard 只容許經過 https訪問,咱們使用nodeport的方式暴露服務,可使用 https://NodeIP:NodePort 地址訪問。

關於自定義證書

默認dashboard的證書是自動生成的,確定是非安全的證書,若是你們有域名和對應的安全證書能夠本身替換掉。使用安全的域名方式訪問dashboard。
在dashboard-all.yaml中增長dashboard啓動參數,能夠指定證書文件,其中證書文件是經過secret注進來的。

--tls-cert-file=dashboard.cer --tls-key-file=dashboard.key

3. 登陸dashboard

Dashboard 默認只支持 token 認證,因此若是使用 KubeConfig 文件,須要在該文件中指定 token,咱們這裏使用token的方式登陸

# 建立service account
$ kubectl create sa dashboard-admin -n kube-system

# 建立角色綁定關係
$ kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin

# 查看dashboard-admin的secret名字
$ ADMIN_SECRET=$(kubectl get secrets -n kube-system | grep dashboard-admin | awk '{print $1}')

# 打印secret的token
$ kubectl describe secret -n kube-system ${ADMIN_SECRET} | grep -E '^token' | awk '{print $2}'

6、部署 metrics-server

metrics-server 經過 kube-apiserver 發現全部節點,而後調用 kubelet APIs(經過 https 接口)得到各節點(Node)和 Pod 的 CPU、Memory 等資源使用狀況。

從 Kubernetes 1.12 開始,kubernetes 的安裝腳本移除了 Heapster,從 1.13 開始徹底移除了對 Heapster 的支持,Heapster 再也不被維護。

1. 安裝 metrics-server

$ cd target/addons
$ git clone https://github.com/kubernetes-incubator/metrics-server.git
$ cd metrics-server/deploy/1.8+/

修改metrics-server-deployment.yaml文件,把 metrics-server 修改成以下命令行參數:

containers:
      - name: metrics-server
        image: wangzan18/metrics-server-amd64:v0.3.6
        args:
          - --cert-dir=/tmp
          - --secure-port=4443
          - --metric-resolution=30s
          - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP
  • --metric-resolution=30s:從 kubelet 採集數據的週期;
  • --kubelet-preferred-address-types:優先使用 InternalIP 來訪問 kubelet,這樣能夠避免節點名稱沒有 DNS 解析記錄時,經過節點名稱調用節點 kubelet API 失敗的狀況(未配置時默認的狀況);

2. 部署

$ cd target/addons/metrics-server/deploy/1.8+/
$ kubectl apply -f .

參考文檔:https://k8s-install.opsnull.com/

相關文章
相關標籤/搜索