1. 程式人生 > >循序漸進的手動安裝k8s筆記-2

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

上一篇筆記中,我嘗試了使用 k8s 1.6 版本安裝一個最簡單的叢集。這一次,我希望能夠增加 node 的數量並且安裝網路外掛,然後配置內部的域名解析功能。

在起初的設想中,我仍然希望不配置各個元件間的認證,只關心功能的正常執行。但在配置的過程中發現 pod 中執行的元件如果要和 kube-apiserver 通訊的話,必須要有相關的認證資訊,要麼使用 ServiceAccount ,要麼配置 kubeconfig 。那麼在仍然希望安裝所進行的配置最少的情況下,我選擇在 kube-apiserver 和 kube-controller-manager 之間配置 CA 和一組服務端證書,來支援 ServiceAccount 的正常使用。

參考資料:

執行環境&軟體版本:

  • Ubuntu 16.04.4 LTS
  • kubernetes v1.6.0
  • etcd v3.0.14
  • docker-ce 18.06.1-ce
  • flannel v0.10.0
  • k8s-dns 1.14.1
  • easyrsa3

角色規劃

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

另外預先規定 clusterIP 使用的網段 10.244.0.0/16,kube-dns 的 service 使用的 IP 為 10.244.0.10

環境準備

首先仍然是下載 kubernetes 1.6.0 和 對應版本的 etcd,並上傳到伺服器。

關閉 swap並在 /etc/fstab 檔案中取消掉自動掛載

sudo swapoff -a
# vim /etc/fstab 或者其他方式

如果系統上安裝了SELinux,需要將其關閉。另外還需要在防火牆上放開下面步驟中所有需要使用的埠,或者關閉防火牆管理軟體,我這裡選擇將ubuntu16.04預設的ufw關閉

sudo ufw disable

安裝 docker-ce ,這裡我選擇新增阿里雲的源並使用 apt-get 安裝:

# step 1: 安裝必要的一些系統工具
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=amd64] 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

為了能夠使叢集節點之間、叢集內外能夠通訊,需要在 docker 的服務檔案 /lib/systemd/system/docker.service 的 [Service] 段中新增下面內容,含義為在啟動 docker 之後,修改 FORWARD 鏈的預設規則為 ACCEPT。

ExecStartPost=/sbin/iptables -P FORWARD ACCEPT

在 /etc/hosts 中配置各個節點的解析,如果這裡不配置節點之間可能無法通過 node 的 name 互相找到。

# 新增如下幾行
192.168.112.148    u16-1
192.168.112.149 u16-2
192.168.112.150 u16-3

安裝 Master 功能

安裝 etcd 服務

tar xf etcd-v3.0.14-linux-amd64.tar.gz
# 把解壓後的 etcd 和 etcdctl 複製到 /usr/bin 目錄下
sudo cp etcd-v3.0.14-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
# 完成後可以檢查一下服務是否正常執行
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

這裡並沒有像上一篇筆記中那樣使用預設配置讓 etcd 只監聽本地迴環的 2379 埠,因為現在除了 kube-apiserver 之外各個 node 上執行 flanneld 也需要使用 etcd ,所以選擇監聽了本機IP的 2379 埠。

引數說明: --listen-client-urls 指定要監聽客戶端流量的URL列表,也就是對客戶端開放的地址和埠。 --advertise-client-urls 指定向客戶端告知的URL列表。

安裝 kube-apiserver 服務

tar xf kubernetes-server-linux-amd64.tar.gz
# 將 kube-apiserver、kube-controller-manager 和 kube-scheduler 的二進位制檔案複製到 /usr/bin 目錄下
sudo cp kubernetes/server/bin/kube-{apiserver,controller-manager,scheduler} /usr/bin/
# 順帶把 kubectl 也放在系統 PATH 中
sudo cp kubernetes/server/bin/kubectl /usr/bin
# 建立日誌存放目錄和配置存放目錄
sudo mkdir /var/log/kubernetes
sudo mkdir /etc/kubernetes

下面需要建立 apiserver 與 controller-manager 之間認證所需要的證書。

# 這裡我準備使用 easy-rsa 工具生成證書。先下載 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 "[email protected]`date +%s`" build-ca nopass
# 建立服務端證書和祕鑰,這裡的 IP 一個是 master 所在 host 的 IP,另一個是 apiserver 的 clusterIP
./easyrsa --subject-alt-name="IP:192.168.112.148,IP:10.244.0.1" build-server-full server nopass
# 建立證書存放目錄並把需要的證書及祕鑰複製
sudo mkdir /etc/kubernetes/pki
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-bind-address=0.0.0.0 \
--insecure-port=8080 \
--service-cluster-ip-range=10.244.0.0/16 \
--service-node-port-range=1-65535 \
--admission_control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \
--client-ca-file=/etc/kubernetes/pki/ca.crt \
--tls-cert-file=/etc/kubernetes/pki/server.crt \
--tls-private-key-file=/etc/kubernetes/pki/server.key \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2"

# 啟動並設定為開機自啟動
sudo systemctl daemon-reload
sudo systemctl start kube-apiserver
sudo systemctl enable kube-apiserver
kube-apiserver 的引數說明: --service-cluster-ip-range :指定叢集 Cluster IP 網段。因為希望使用 10.244.0.0/16 作為使用的網段,所以在這裡指定。 --admission_control :Kubernetes 叢集的准入控制設定,各控制模組以外掛形式依次生效。因為 pod 中執行的外掛需要使用 serviceaccount ,所以這次不刪除 ServiceAccount 模組。 --client-ca-file :指定CA根證書檔案 --tls-cert-file :指定服務端證書檔案 --tls-private-key-file :指定服務端私鑰檔案

安裝 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="--master=http://192.168.112.148:8080 \
--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 引數說明: --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

安裝 kube-scheduler 服務

這部分配置與上一篇筆記完全相同。編輯 systemd 服務檔案 /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

環境變數檔案 /etc/kubernetes/scheduler 中定義了 kube-scheduler 啟動引數 KUBE_SCHEDULER_ARGS。我們建立這個檔案並填入如下內容

KUBE_SCHEDULER_ARGS="--master=http://192.168.112.148:8080 \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2"

安裝完 kube-controller-manager 和 kube-scheduler 之後將其啟動並設定為開機自啟動

sudo systemctl daemon-reload
sudo systemctl start kube-scheduler
sudo systemctl enable kube-scheduler

以上,master 角色的功能已經安裝完成。下面需要在所有的節點安裝 node 角色的功能。

安裝 node 功能

安裝 kubelet 和 kube-proxy 的過程與上篇筆記基本相同。

安裝 kubelet 和 kube-proxy

tar xf kubernetes-server-linux-amd64.tar.gz
# 將 kubelet 和 kube-proxy 的二進位制檔案複製到 /usr/bin 目錄下
sudo cp kubernetes/server/bin/kube{let,-proxy} /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
# 下一步分別建立 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.targe

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/kubelet 
KUBELET_ARGS="--api-servers=http://192.168.112.148:8080 \
--hostname-override=u16-1 \
--cgroups-per-qos=false \
--enforce-node-allocatable="" \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2"

cat /etc/kubernetes/proxy 
KUBE_PROXY_ARGS="--master=http://192.168.112.148:8080 --logtostderr=false --log-dir=/var/log/kubernetes --v=2"

# 將這兩個服務啟動並設定為開機自動啟動
sudo systemctl start kubelet kube-proxy && sudo systemctl enable kubelet kube-proxy
--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" }'

然後就可以啟動 flanneld 了

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

下面我們可以建立幾個 在不用 node 上執行的 pod 來測試網路是否已經聯通。

# 還是先解決基礎映象的問題 
sudo docker image pull mirrorgooglecontainers/pause-amd64:3.0
sudo docker tag mirrorgooglecontainers/pause-amd64:3.0 gcr.io/google_containers/pause-amd64:3.0
# 然後建立一個 yaml 檔案用於配置測試用的資源
cat test.yml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
---
apiVersion: v1
kind: Pod
metadata:
  name: client
spec:
  restartPolicy: OnFailure
  containers:
  - name: curl
    image: appropriate/curl
    args:
    - /bin/sh
    - -c
    - sleep 6000

# 建立資源
kubectl apply -f test.yml 
kubectl get pod -o wide
# 檢查 NODE 列,因為要測試不同 node 上是否可以互相通訊,所以希望這裡2個 pod 不在一個 node 上。
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
client                   1/1       Running   0          2m        10.244.62.2   u16-1
nginx-3406752312-7z5fs   1/1       Running   0          2m        10.244.18.2   u16-2
# 之後進入 client pod 的 容器內測試連線 nginx POD 的服務,看是否能夠正常訪問。
kubectl exec -it client /bin/sh
# 下面為在容器內操作
curl 10.244.18.2
# 顯示訪問正常
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
…………

安裝外掛

我在這裡只嘗試安裝了 kube-dns 外掛,希望達到的目標是 k8s 內的容器在建立時都會指定 kube-dns 外掛的地址為 dns 伺服器,並且這個 dns 可以解析叢集建立的 service 的地址。

kube-dns 的安裝是將 kube-dns 作為一個 deployment 部署,它的 yaml 檔案在 k8s 原始碼包內。

# 原始碼包已經包含在我們下載的二進位制安裝包內了,先解壓
cd kubernetes/
tar xf kubernetes-src.tar.gz
cd cluster/addons/dns
# 將需要修改的檔案複製一份並作出修改,將模板改中的變數改為實際的值
cp kubedns-svc.yaml.sed kubedns-svc.yaml
cp kubedns-controller.yaml.sed kubedns-controller.yaml
sed -i 's/$DNS_SERVER_IP/10.244.0.10/g' kubedns-svc.yaml
sed -i 's/$DNS_DOMAIN/cluster.local/g' kubedns-controller.yaml
# 建立 kube-dns 所需要的 configmap、serviceaccount、service和deployment
kubectl apply -f kubedns-cm.yaml
kubectl apply -f kubedns-sa.yaml --namespace=kube-system
# sa 的模板中並沒有指定 namespace ,其他模板中指定了,不知道什麼原因,但我在這裡需要將 serviceaccount 建立在 kube-system 的 namespace 下。
kubectl apply -f kubedns-svc.yaml
kubectl apply -f kubedns-controller.yaml
# 檢視 dns 是否正常執行,這裡 READY 為 3/3,STATUS 為 Running 表示執行成功
kubectl get pod -n kube-system

安裝完成 kube-dns 後,還需要在所有 kubelet 的啟動引數中增加下面引數,然後重啟 kubelet。

--cluster-dns=10.244.0.10 --cluster-domain=cluster.local

測試一下功能

# 回到剛才的 test.yml 所在的目錄,刪除掉剛才的資源並重新建立
kubectl delete -f test.yml
kubectl apply -f test.yml
# 再建立檔案用於 nginx 的svc 
cat test-svc.yml 
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
# 建立 svc
kubectl apply -f test-svc.yml
# 之後進入 client pod 的容器內測試通過 svc 的名字連線 nginx POD 的服務,看是否能夠正常訪問。
kubectl exec -it client /bin/sh
# 下面為在容器內操作
curl http://nginx-svc
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
…………
# 因為此時新部署的pod都已經自動配置了 kube-dns 作為 dns 伺服器。可以檢視 /etc/resolv.conf 
cat /etc/resolv.conf 
nameserver 10.244.0.10
search default.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5

至此,一個多 node 間的 pod 可以互相通訊,並且可以通過 dns 來訪問或者進行服務發現的 k8s 叢集已經部署完成。