天天看點

循序漸進的手動安裝k8s筆記-3

在上一篇筆記中,我們已經可以使用 k8s1.6 版本搭建一個基礎的叢集,在叢集内部可以完成不同 node 之間的 pod 互通并且可以完成服務發現。但已經完成的這個叢集仍然是通過不安全的 8080 端口進行的,并且除了最基本的 apiserver 和 controller-manager 之間以外,其他元件間通訊都沒有認證措施。這一次,我準備在叢集中加入 TLS 驗證來加強叢集的安全性,不過這次隻加入認證并不考慮授權,同時加入 kubeconfig 配置檔案的機制,将apiserver位址和一些用戶端證書存放在 kubeconfig 配置檔案中。再安裝一個新的插件 Dashboard ,用于以web方式管理叢集。

這次使用的 k8s 版本是比較新的 1.10.8 。第一個原因是已經決 定使用 kubeconfig 來進行配置是以舊版本不是必須的,另一個原因是在使用 tls 證書時 1.6.0 版本出現了一些 bug,是以就決定直接将 k8s 更換成比較新的版本。到目前為止 k8s 仍在快速疊代,是以建議在使用的時候選擇新一些的版本。

參考資料:

運作環境&軟體版本:

  • Ubuntu 16.04.4 LTS
  • kubernetes v1.10.8
  • etcd v3.1.12
  • docker-ce 18.06.1-ce
  • flannel v0.10.0
  • coredns 1.0.6
  • easyrsa3
  • kubernetes-dashboard v1.8.3

角色規劃:

主機名 IP位址 角色 CPU/記憶體
u16-1 192.168.112.148 master 2核/2G
u16-2 192.168.112.149 node
u16-3 192.168.112.150

上一篇筆記中關于 clusterIP 了解有些錯誤,clusterIP 是 service 使用的 IP 位址段,和 pod 使用的 ip 位址段不是同一個配置,并且應該無重合部分(與實體機IP段也不要有重合部分)。這次指定 clusterIP 端為 10.0.0.0/16 ,kube-dns 的 service 使用的 IP 位址為 10.0.0.10

環境準備

準備工作基本可以歸納為以下幾步

  1. 下載下傳需要的 kubernetes etcd 的二進制版本并上傳至伺服器。(etcd 的版本選擇可以從 k8s 源碼包中 kubernetes/cluster/images/etcd/Makefile 檔案的 REGISTRY_TAG? 字段找到)
  2. 在節點上禁用 swap 和 selinux。
  3. 配置防火牆放開各個元件使用的端口或者關閉防火牆管理軟體。雖然不使用防火牆管理軟體(ufw、Firewalld),但k8s仍然會操作 iptables 表用來實作通路 service 等功能。
  4. 設定以下核心參數,可以在 /etc/sysctl.conf 檔案或者等效的其他檔案内填寫
    net.ipv4.ip_forward = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1           
    部分發行版本的 linux 可能不預設加載 br_netfilter 子產品導緻無法加載後兩條規則,如果缺少子產品需要提前配置加載,這裡不詳細介紹過程了。
  5. 安裝 docker-ce 并且配置在啟動 docker 之後,修改 FORWARD 鍊的預設規則為 ACCEPT。具體可以參考上一篇筆記。
  6. 如果有内部 DNS,可以在内部 DNS 上配置各個節點間可以通過主機名互相解析。如果沒有則需要配置 /etc/hosts 解析各個節點,像下面這樣:
    # 添加如下幾行
    192.168.112.148 u16-1
    192.168.112.149 u16-2
    192.168.112.150 u16-3           

安裝 Master 功能

安裝 etcd 服務

$ tar xf etcd-v3.1.12-linux-amd64.tar.gz
# 把解壓後的 etcd 和 etcdctl 複制到 /usr/bin 目錄下
$ sudo cp etcd-v3.1.12-linux-amd64/etcd{,ctl} /usr/bin/
# 建立 etcd 工作路徑和配置存放路徑
$ sudo mkdir /var/lib/etcd/
$ sudo mkdir /etc/etcd
# 然後建立管理腳本 /lib/systemd/system/etcd.service 和配置檔案 /etc/etcd/etcd.conf。内容如下
$ cat /lib/systemd/system/etcd.service 
[Unit]
Description=Etcd Server
After=network.target
[Service]
Type=notify
WorkingDirectory=/var/lib/etcd
EnvironmentFile=-/etc/etcd/etcd.conf
ExecStart=/usr/bin/etcd $ETCD_ARGS
[Install]
WantedBy=multi-user.target

$ cat /etc/etcd/etcd.conf 
ETCD_ARGS="--listen-client-urls 'http://192.168.112.148:2379' --advertise-client-urls 'http://192.168.112.148:2379'" # 啟動并設定為開機自啟動
$ sudo systemctl daemon-reload
$ sudo systemctl start etcd
$ sudo systemctl enable etcd
Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /lib/systemd/system/etcd.service.

# 完成後可以檢查一下服務是否正常運作
systemctl status etcd
# 也可以使用 etcdctl 來檢查 etcd 健康狀況
$ etcdctl --endpoints http://192.168.112.148:2379 cluster-health
member 8e9e05c52164694d is healthy: got healthy result from http://192.168.112.148:2379
cluster is healthy           

安裝 kube-apiserver 服務

# 解壓二進制檔案并将 kube-apiserver 複制到系統目錄 /usr/bin
$ tar xf kubernetes-server-linux-amd64.tar.gz 
$ sudo cp kubernetes/server/bin/kube-apiserver /usr/bin/
# 順便把其他 master 的元件都複制到系統目錄 /usr/bin 
$ sudo cp kubernetes/server/bin/{kube-controller-manager,kube-scheduler,kubectl} /usr/bin/
# 建立日志存放目錄和配置存放目錄
$ sudo mkdir /var/log/kubernetes
$ sudo mkdir /etc/kubernetes           

然後建立各個元件間認證的證書,因為這一次的目的是建立一個隻通過 tls 證書認證元件而不做對應授權的叢集,同時也沒有開啟 RBAC,是以這裡就簡化配置,隻建立一組 CA 證書用于簽名用戶端和服務端證書、一組服務端證書用于 apiserver 、一組用戶端證書用于其他元件。

# 因為這次不需要對證書配置過多的屬性,是以還是使用上次使用的 easy-rsa 工具來建立證書并簽名
$ curl -L -O https://storage.googleapis.com/kubernetes-release/easy-rsa/easy-rsa.tar.gz
$ tar xf easy-rsa.tar.gz
$ cd easy-rsa-master/easyrsa3/
# 初始化工具
$ ./easyrsa init-pki
# 建立根證書(CA)
$ ./easyrsa --batch --req-cn=kubernetes build-ca nopass
# 建立服務端證書和秘鑰
$ ./easyrsa --subject-alt-name="IP:192.168.112.148,IP:10.0.0.1,IP:127.0.0.1,DNS:kubernetes.default" build-server-full server nopass
# 建立用戶端證書和秘鑰
$ ./easyrsa build-client-full client nopass
# 使用 kubectl 建立 kubeconfig 檔案供用戶端和其他元件使用
$ kubectl config set-cluster kubernetes \
> --certificate-authority=pki/ca.crt \
> --embed-certs=true \
> --server=https://192.168.112.148:6443 \
> --kubeconfig=./client.conf
Cluster "kubernetes" set.

$ kubectl config set-credentials client \
> --client-certificate=pki/issued/client.crt \
> --client-key=pki/private/client.key \
> --embed-certs=true \
> --kubeconfig=./client.conf 
User "client" set.

$ kubectl config set-context client@kubernetes \
> --cluster=kubernetes \
> --user=client \
> --kubeconfig=./client.conf 
Context "client@kubernetes" created.

$ kubectl config use-context client@kubernetes \
> --kubeconfig=./client.conf 
Switched to context "client@kubernetes".

# 将生成的 kubeconfig 放在 kubectl 預設讀取配置的位置并重命名成 config。
$ cp client.conf ~/.kube/config
# 将 kubeconfig 和證書放在配置檔案的目錄
$ sudo mkdir /etc/kubernetes/pki
$ sudo cp client.conf /etc/kubernetes/
$ sudo cp pki/ca.crt pki/issued/server.crt pki/private/server.key /etc/kubernetes/pki/           

然後建立管理腳本 /lib/systemd/system/kube-apiserver.service 和配置檔案 /etc/kubernetes/apiserver

$ cat /lib/systemd/system/kube-apiserver.service 
[Unit]
Description=Kubernetes API Server
After=etcd.service
Wants=etcd.service
[Service]
EnvironmentFile=/etc/kubernetes/apiserver
ExecStart=/usr/bin/kube-apiserver $KUBE_API_ARGS
Restart=on-failure
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

$ cat /etc/kubernetes/apiserver 
KUBE_API_ARGS="--storage-backend=etcd3 --etcd-servers=http://192.168.112.148:2379 --insecure-port=0 --service-cluster-ip-range=10.0.0.0/16 --service-node-port-range=1-65535 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota --logtostderr=false --log-dir=/var/log/kubernetes --v=2 --client-ca-file=/etc/kubernetes/pki/ca.crt --tls-private-key-file=/etc/kubernetes/pki/server.key --tls-cert-file=/etc/kubernetes/pki/server.crt" # 啟動并設定為開機自啟動
$ sudo systemctl daemon-reload
$ sudo systemctl start kube-apiserver
$ sudo systemctl enable kube-apiserver
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-apiserver.service to /lib/systemd/system/kube-apiserver.service.

# 此時 kube-apiserver 已經啟動并且僅在 6443 端口監聽。
$ sudo netstat -lnpt|grep apiserver 
tcp6 0 0 :::6443 :::* LISTEN 8781/kube-apiserver

# kubectl 預設情況下連結的 API 位址是本地的 8080 端口,是以需要設定 ~/.kube/config 檔案, kubectl 才能正确的找到 API 伺服器位址。
$ kubectl cluster-info
Kubernetes master is running at https://192.168.112.148:6443
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.           

安裝 kube-controller-manager 服務

上一步已經将需要的二進制可執行檔案和證書秘鑰放在相應的位置了,下面需要建立管理腳本 /lib/systemd/system/kube-controller-manager.service 和 配置檔案 /etc/kubernetes/controller-manager

$ cat /lib/systemd/system/kube-controller-manager.service 
[Unit]
Description=Kubernetes Controller Manager
After=kube-apiserver.service
Requires=kube-apiserver.service
[Service]
EnvironmentFile=/etc/kubernetes/controller-manager
ExecStart=/usr/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_ARGS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

$ cat /etc/kubernetes/controller-manager 
KUBE_CONTROLLER_MANAGER_ARGS="--kubeconfig=/etc/kubernetes/client.conf --service-account-private-key-file=/etc/kubernetes/pki/server.key --root-ca-file=/etc/kubernetes/pki/ca.crt --logtostderr=false --log-dir=/var/log/kubernetes --v=2"           

kube-controller-manager 參數說明:

--kubeconfig :在 kubeconfig 檔案中指定 apiserver 位址、服務端證書和用戶端證書與秘鑰

--service-account-private-key-file :指定服務端私鑰。用于簽署 serviceaccount 的 token。

--root-ca-file :指定 ca 跟證書檔案。配置了此項後,ca證書将被包含在 serviceaccount 中,然後就可以使用 serviceaccount 認證 元件與apiserver 間的通訊。

啟動并設定為開機自啟動

$ sudo systemctl daemon-reload
$ sudo systemctl start kube-controller-manager
$ sudo systemctl enable kube-controller-manager
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-controller-manager.service to /lib/systemd/system/kube-controller-manager.service.           

安裝 kube-scheduler 服務

二進制檔案和 kubeconfig 檔案已經就緒,下面需要建立管理腳本 /lib/systemd/system/kube-scheduler.service 和配置檔案 /etc/kubernetes/scheduler

$ cat /lib/systemd/system/kube-scheduler.service 
[Unit]
Description=Kubernetes Scheduler Server
After=kube-apiserver.service
Requires=kube-apiserver.service
[Service]
EnvironmentFile=/etc/kubernetes/scheduler
ExecStart=/usr/bin/kube-scheduler $KUBE_SCHEDULER_ARGS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

$ cat /etc/kubernetes/scheduler 
KUBE_SCHEDULER_ARGS="--kubeconfig=/etc/kubernetes/client.conf --logtostderr=false --log-dir=/var/log/kubernetes --v=2" # 啟動并設定為開機自啟動
$ sudo systemctl daemon-reload
$ sudo systemctl start kube-scheduler
$ sudo systemctl enable kube-scheduler
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-scheduler.service to /lib/systemd/system/kube-scheduler.service.           

安裝 node 功能

在所有節點上操作安裝如下元件。

安裝 kubelet 和 kube-proxy

$ tar xf kubernetes-server-linux-amd64.tar.gz
# 将 kubelet 和 kube-proxy 的二進制檔案複制到 /usr/bin 目錄下
$ sudo cp kubernetes/server/bin/{kube-proxy,kubelet} /usr/bin/
# 建立 kubelet 的工作路徑 /var/lib/kubelet 、配置檔案的存放路徑 /etc/kubernetes 和 日志路徑 /var/log/kubernetes。master 節點上已經建立過的檔案夾則不需要再次建立
$ sudo mkdir /var/lib/kubelet
$ sudo mkdir /var/log/kubernetes
$ sudo mkdir /etc/kubernetes
# 建立完配置檔案夾後,還需要将 client.conf 檔案複制到所有節點的這個檔案夾下 # 下一步分别建立 kubelet 和 kube-proxy 的管理腳本與配置檔案,内容如下
$ cat /lib/systemd/system/kubelet.service 
[Unit]
Description=Kubernetes Kubelet Server
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
EnvironmentFile=/etc/kubernetes/kubelet
ExecStart=/usr/bin/kubelet $KUBELET_ARGS
Restart=on-failure
[Install]
WantedBy=mulit-user.target

$ cat /etc/kubernetes/kubelet 
KUBELET_ARGS="--kubeconfig=/etc/kubernetes/client.conf --hostname-override=u16-1 --logtostderr=false --log-dir=/var/log/kubernetes --v=2"

$ cat /lib/systemd/system/kube-proxy.service 
[Unit]
Description=Kubernetes Kube-Proxy Server
After=networking.service
Requires=networking.service
[Service]
EnvironmentFile=/etc/kubernetes/proxy
ExecStart=/usr/bin/kube-proxy $KUBE_PROXY_ARGS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

$ cat /etc/kubernetes/proxy
KUBE_PROXY_ARGS="--kubeconfig=/etc/kubernetes/client.conf --logtostderr=false --log-dir=/var/log/kubernetes --v=2" # 啟動并設定為開機自啟動
$ sudo systemctl daemon-reload
$ sudo systemctl start kubelet kube-proxy
$ sudo systemctl enable kubelet kube-proxy
Created symlink from /etc/systemd/system/mulit-user.target.wants/kubelet.service to /lib/systemd/system/kubelet.service.
Created symlink from /etc/systemd/system/multi-user.target.wants/kube-proxy.service to /lib/systemd/system/kube-proxy.service.           
--hostname-override ,設定本節點顯示的名字,需要與/etc/hosts 中的解析對應

安裝 flanneld 網絡插件

此部分與上一篇筆記基本相同

wget 下載下傳 flannel 對應版本的二進制程式包,也可以在 github 上

下載下傳

$ wget https://github.com/coreos/flannel/releases/download/v0.10.0/flannel-v0.10.0-linux-amd64.tar.gz
# 解壓出需要的程式放在 /usr/bin 下
$ tar xf flannel-v0.10.0-linux-amd64.tar.gz
$ sudo cp flanneld /usr/bin/
$ sudo cp mk-docker-opts.sh /usr/bin/           

建立 systemd 管理腳本 /lib/systemd/system/flanneld.service。内容如下:

$ cat /lib/systemd/system/flanneld.service 
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
Before=docker.service
[Service]
EnvironmentFile=-/etc/kubernetes/flanneld
ExecStart=/usr/bin/flanneld ${FLANNEL_ETCD} ${FLANNEL_OPTIONS}
ExecStartPost=/usr/bin/mk-docker-opts.sh -d /run/flannel/docker
Type=notify
[Install]
WantedBy=multi-user.target
RequiredBy=docker.service           

建立 flanneld 的配置檔案:

$ cat /etc/kubernetes/flanneld 
FLANNEL_ETCD="-etcd-endpoints=http://192.168.112.148:2379"
FLANNEL_ETCD_KEY="/coreos.com/network"           

同時還需要修改 /lib/systemd/system/docker.service 。在 After= 和 Requires= 後添加 flanneld.service 。添加環境變量檔案 EnvironmentFile=-/run/flannel/docker ,同時在 ExecStart= 後面添加環境變量 DOCKER_OPTS , 比如:ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_OPTS

flannel 網絡插件使用 etcd 存儲和同步資訊,在啟動 flanneld 之前首先主節點上配置 etcd 中設定初始的配置:

$ etcdctl --endpoints http://192.168.112.148:2379 set /coreos.com/network/config '{ "Network": "10.244.0.0/16" }'
{ "Network": "10.244.0.0/16" }           

然後就可以啟動 flanneld 了

$ sudo systemctl daemon-reload
$ sudo systemctl start flanneld && sudo systemctl enable flanneld
# 啟動 flanneld 之後還需要重新開機 docker 和 kubelet
$ sudo systemctl restart docker kubelet
# 之後檢視本機網卡資訊,docker0 的 ip 位址已經變為指定的 ip 段。           

解決基礎鏡像下載下傳

這個版本 k8s 使用的基礎鏡像為 k8s.gcr.io/pause-amd64:3.1 ,因為一些原因不能直接下載下傳到,是以可以通過在 dockerhub 上下載下傳相同鏡像然後重新設定标簽的方式解決。

sudo docker image pull mirrorgooglecontainers/pause-amd64:3.1
sudo docker tag mirrorgooglecontainers/pause-amd64:3.1 k8s.gcr.io/pause-amd64:3.1           

安裝插件

安裝 coredns 插件

嘗試在節點間使用 tls 加密通信後 dns 插件能否安裝成功。

# 源碼包已經包含在我們下載下傳的二進制安裝包内了,先解壓
$ cd kubernetes/
$ tar xf kubernetes-src.tar.gz
$ cd cluster/addons/dns
# 将需要修改的檔案複制一份并作出修改,将模闆改中的變量改為實際的值。和舊版本不同,這個版本将原來的單獨的 svc、configmap、sa、deploy 都放進一個配置檔案 kube-dns.yaml。同時還提供了更強大的 coredns 用來替代 kube-dns。這次嘗試安裝 coredns 插件
$ cp coredns.yaml.sed coredns.yaml
$ sed -i 's/$DNS_SERVER_IP/10.0.0.10/g' coredns.yaml
$ sed -i 's/$DNS_DOMAIN/cluster.local/g' coredns.yaml
# 因為這次我們不使用包括 rbac 在内的任何鑒權方式,是以可以手動删除掉這個配置檔案中 kind 為 ClusterRole 和 ClusterRoleBinding 的配置段。然後使用 kubectl 建立配置檔案對應的資源。
$ kubectl apply -f coredns.yaml
# 檢視 dns 是否正常運作,與之前 kube-dns 存在三個容器在一個 POD 中不同, coredns 建立了1個容器在一個 POD 中,同時 replicas 設定為2,就是說有2個相同的 POD 為 DNS 服務提供負載均衡
$ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-77c989547b-7mk6s 1/1 Running 1 3m
coredns-77c989547b-b9g55 1/1 Running 1 2m           

安裝 Dashboard 插件

Dashboard 是 k8s 自帶的 web UI 管理界面,可以通過圖形化的方式檢視叢集狀态以及對叢集進行操作。

# k8s 也在源碼包内提供了 Dashboard 的配置檔案,路徑為 kubernetes/cluster/addons/dashboard ,也就是說和 dns 插件所在的檔案夾擁有同樣一個上級目錄。
$ cd ../dashboard/
$ ls -l
總用量 32
-rw-rw-r-- 1 sun sun 264 9月 13 23:17 dashboard-configmap.yaml
-rw-rw-r-- 1 sun sun 1754 9月 13 23:17 dashboard-controller.yaml
-rw-rw-r-- 1 sun sun 1353 9月 13 23:17 dashboard-rbac.yaml
-rw-rw-r-- 1 sun sun 551 9月 13 23:17 dashboard-secret.yaml
-rw-rw-r-- 1 sun sun 359 9月 27 14:04 dashboard-service.yaml
-rw-rw-r-- 1 sun sun 242 9月 13 23:17 MAINTAINERS.md
-rw-rw-r-- 1 sun sun 72 9月 13 23:17 OWNERS
-rw-rw-r-- 1 sun sun 400 9月 13 23:17 README.md
# dashboard 的 image 存放在 google 的鏡像倉庫,無法直接下載下傳。是以這裡還是先找到這個鏡像的名字,然後在 dockerhub 上下載下傳相同鏡像并修改 tag 。
$ grep 'image:' dashboard-controller.yaml 
 image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3
$ sudo docker image pull mirrorgooglecontainers/kubernetes-dashboard-amd64:v1.8.3
$ sudo docker image tag mirrorgooglecontainers/kubernetes-dashboard-amd64:v1.8.3 k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3
# 這裡為了通路友善,修改一下 service 的配置檔案,把 type 設定為 NodeProt 模式并設定一個固定的 nodePort
$ cat dashboard-service.yaml 
apiVersion: v1
kind: Service
metadata:
 name: kubernetes-dashboard
 namespace: kube-system
 labels:           

本文轉自SegmentFault-

循序漸進的手動安裝k8s筆記-3