不知道有沒有人和我同樣,在手動安裝時由於不少緣由沒有成功(主要仍是知識儲備不夠),被各類高可用配置和各類證書權限弄得迷迷糊糊。這個筆記是我在嘗試了不少種手動安裝Kubernetes集羣教程中的方法失敗後產生的想法,但願可以將複雜的配置化繁爲簡,呈現出一個基本功能的Kubernetes程序,記錄下如何以最簡的方式配置各個組件,使其可以實現基本的功能。而後再逐步添加多節點、安全認證、高可用等複雜配置,經過這個過程來理解Kubernetes各類基礎組件之間的關係已經配置方法。html
計劃的第一步就是完成一個非安全的單 master 單 node 集羣,api-server 和 kubelet 等組件都經過systemd來管理,master 上不安裝kubelet 只作管理端使用。首先我嘗試用比較新的 1.10.X 版k8s 安裝,可是安裝過程當中沒有辦法用非證書認證方式指定 api-server 的地址,彷佛官方在有意逐步取消對非安全方式的支持。最後仍是選擇了比較舊的k8s 1.6.0 來完成安裝。node
主機名 | IP地址 | 角色 | CPU/內存 |
---|---|---|---|
u16-1 | 192.168.112.148 | master(only as master) | 2核/2G |
u16-2 | 192.168.112.149 | node | 2核/2G |
從 github 的 Kubernetes 項目頁面 上找到咱們須要的 V1.6.0版本,而後點擊 CHANGELOG,在 Older releases 下面點擊 CHANGELOG-1.6.md ,找到 v1.6.0 版本的 Server Binaries 中對應的架構的包(kubernetes-server-linux-amd64.tar.gz)下載並上傳到服務器(國內上網環境可能沒法正常下載)linux
k8s 1.6.0 對應的 etcd 版本爲 v3.0.14,一樣能夠從 github 上 etcd 項目對應版本的頁面找到並下載到服務器git
wget https://github.com/etcd-io/etcd/releases/download/v3.0.14/etcd-v3.0.14-linux-amd64.tar.gz
關閉 swap並在 /etc/fstab 文件中取消掉自動掛載github
sudo swapoff -a
若是系統上安裝了SELinux,須要將其關閉。另外還須要在防火牆上放開下面步驟中全部須要使用的端口,或者關閉防火牆管理軟件,我這裏選擇將ubuntu16.04默認的ufw關閉docker
sudo ufw disable
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/
而後設置 systemd 服務文件 /lib/systemd/system/etcd.serviceubuntu
[Unit] Description=Etcd Server After=network.target [Service] Type=notify WorkingDirectory=/var/lib/etcd/ EnvironmentFile=-/etc/etcd/etcd.conf ExecStart=/usr/bin/etcd [Install] WantedBy=multi-user.target
這裏 WorkingDirectory 指定的目錄須要提早建立好,這個目錄將做爲etcd數據保存的目錄。api
EnvironmentFile 能夠指定 etcd 的配置文件。在我這裏由於只是測試安裝,因此 etcd 使用默認配置就能夠了。安全
經過 systemd 啓動 etcd 並設置爲開機自啓動bash
sudo systemctl daemon-reload sudo systemctl start etcd sudo systemctl enable etcd # 完成後能夠檢查一下服務是否正常運行 systemctl status etcd # 也可使用 etcdctl 來檢查 etcd 健康情況 etcdctl cluster-health # 正常的輸出爲: # member 8e9e05c52164694d is healthy: got healthy result from http://localhost:2379 # cluster is healthy
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/
編輯 systemd 服務文件 /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
環境變量文件 /etc/kubernetes/apiserver 中定義了 kube-apiserver 啓動參數 KUBE_API_ARGS。咱們建立這個文件並填入以下內容
KUBE_API_ARGS="--storage-backend=etcd3 --etcd-servers=http://127.0.0.1:2379 \ --insecure-bind-address=0.0.0.0 --insecure-port=8080 \ --service-cluster-ip-range=169.169.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"
參數說明:
--storage-backend :指定 etcd 版本。
--etcd-servers :指定 etcd 服務器地址和端口。
--insecure-bind-address :指定 api-server 非安全方式綁定的地址。0.0.0.0 表示全部地址。
--insecure-port :指定 api-server 非安全方式啓用的端口號。
--service-cluster-ip-range :指定集羣 Cluster IP 網段,若是後續須要使用網絡插件這裏須要按照網絡插件要求的網段配置。
--service-node-port-range :指定集羣中 Service 能夠映射物理機端口號範圍
--admission_control :Kubernetes 集羣的准入控制設置,各控制模塊以插件形式依次生效。
--logtostderr :指定爲 false 時將錯誤日誌寫入日誌文件而非 標準輸出。
--log-dir :日誌保存路徑。
--v :日誌級別
經過 systemd 啓動 kube-apiserver 並設置爲開機自啓動
sudo systemctl daemon-reload sudo systemctl start kube-apiserver sudo systemctl enable kube-apiserver # 以後能夠經過 status 來檢查服務器運行狀態 systemctl status kube-apiserver
編輯 systemd 服務文件 /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
環境變量文件 /etc/kubernetes/controller-manager 中定義了 kube-controller-manager 啓動參數 KUBE_CONTROLLER_MANAGER_ARGS。咱們建立這個文件並填入以下內容
KUBE_CONTROLLER_MANAGER_ARGS="--master=http://192.168.112.148:8080 \ --logtostderr=false \ --log-dir=/var/log/kubernetes \ --v=2"
參數說明:--master :指定 API-server 的URL地址
編輯 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-controller-manager kube-scheduler sudo systemctl enable kube-controller-manager kube-scheduler # 一樣,啓動以後能夠經過 systemctl status XXXX 來檢查服務的狀態 systemctl status kube-controller-manager systemctl status kube-scheduler.service
master 上的安裝已經完成,下一步就要開始安裝 node 節點上須要的服務了。
node 節點上須要安裝的服務有 docker 、kubelet 和 kube-proxy。
安裝 docker 的方式不少,在這裏我使用添加阿里雲的源並使用 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 就是啓動狀態而且設置了開機自啓。
tar xf kubernetes-server-linux-amd64.tar.gz # 將 kubelet 和 kube-proxy 的二進制文件複製到 /usr/bin 目錄下 sudo cp kubernetes/server/bin/kube{let,-proxy} /usr/bin/
編輯 systemd 服務文件 /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
WorkingDirectory 指定的路徑是 kubelet 的數據目錄,須要在服務運行前建立提早建立。
環境變量文件 /etc/kubernetes/kubelet 中定義了 kubelet 啓動參數 KUBELET_ARGS。咱們建立這個文件並填入以下內容
KUBELET_ARGS="--api-servers=http://192.168.112.148:8080 \ --hostname-override=u16-2 \ --logtostderr=false \ --log-dir=/var/log/kubernetes \ --v=2"
參數說明:--api-servers :指定 apiserver 的URL地址。
--hostname-override :指定註冊到 apiserver 時本節點的名稱。
經過 systemd 啓動 kubelet 並設置爲開機自啓動
sudo systemctl daemon-reload sudo systemctl start kubelet sudo systemctl enable kubelet # 以後能夠經過 status 來檢查服務器運行狀態 systemctl status kubelet
編輯 systemd 服務文件 /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
環境變量文件 /etc/kubernetes/proxy 中定義了 kube-proxy 啓動參數 KUBE_PROXY_ARGS。咱們建立這個文件並填入以下內容
KUBE_PROXY_ARGS="--master=http://192.168.112.148:8080 \ --logtostderr=false \ --log-dir=/var/log/kubernetes \ --v=2"
經過 systemd 啓動 kubu-proxy 並設置爲開機自啓動
sudo systemctl daemon-reload sudo systemctl start kube-proxy sudo systemctl enable kube-proxy # 以後能夠經過 status 來檢查服務器運行狀態 systemctl status kube-proxy
node 節點設置完成後, 若是 master 節點上有 kubernetes 的命令行管理軟件 kubectl ,就可使用kubectl 查看到新增長的節點。kubectl 的二進制文件能夠從 kubernetes-server-linux-amd64.tar.gz 中找到。
sudo cp kubernetes/server/bin/kubectl /usr/bin/ sudo chmod +x /usr/bin/kubectl kubectl get node # 輸出爲 # NAME STATUS AGE VERSION # u16-2 NotReady 17m v1.6.0
這時能夠看到新增長的節點 u16-2 的狀態爲 NotReady,經過命令來查看 node 狀態
kubectl describe node u16-2
這時能夠在 Events: 中看到一條報錯,Massage是
Failed to start ContainerManager failed to initialise top level QOS containers: root container /kubepods doesn't exist
解決辦法參考這裏,在kubelet 的啓動參數中加上下面參數並重啓
--cgroups-per-qos=false --enforce-node-allocatable=""
重啓後 node 變爲 Ready 狀態。
# 在集羣上運行 kubernetes-bootcamp 鏡像 kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080 # 由於上面命令中的鏡像位置在國內可能也沒法正常訪問 因此能夠將其替換爲 dockerhub 上相同的鏡像 jocatalin/kubernetes-bootcamp:v1 kubectl run kubernetes-bootcamp --image=jocatalin/kubernetes-bootcamp:v1 --port=8080 # 檢查 deployment 運行狀態 kubectl get deployment # ---顯示以下--- NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE kubernetes-bootcamp 1 0 0 0 4m # 當前的 Pod 數一直爲0,檢查一下 deployment 狀態 kubectl describe deployment kubernetes-bootcamp # Events 中最後的信息爲 Scaled up replica set kubernetes-bootcamp-4025819334 to 1 ,再看一下 replicaSet 的狀態 kubectl describe replicaset kubernetes-bootcamp-4025819334
發現 Events 中的報錯:
Error creating: No API token found for service account "default", retry after the token is automatically created and added to the service account
解決方法參考這裏,由於這裏搭建的整個集羣都是無安全認證的,因此將 api-server 中的 --admission_control 參數裏的 ServiceAccount 刪除,並重啓 kube-apiserver 。
以後再次查看 deployment 狀態
kubectl get deployment # ---顯示以下--- NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE kubernetes-bootcamp 1 1 1 0 18m
此次 pod 成功建立了,但仍然不是 AVAILABLE 狀態。
# 查看現有的 pod kubectl get pod # ---顯示以下--- NAME READY STATUS RESTARTS AGE kubernetes-bootcamp-4025819334-q61xj 0/1 ContainerCreating 0 5m # 查看這個 Pod 的詳細信息 kubectl describe pod kubernetes-bootcamp-4025819334-q61xj # 在Events 裏看到了錯誤信息: # Error syncing pod, skipping: failed to "CreatePodSandbox" for "kubernetes-bootcamp-4025819334-q61xj_default(1d20e7af-af48-11e8-bf2f-000c29a01556)" with CreatePodSandboxError: "CreatePodSandbox for pod \"kubernetes-bootcamp-4025819334-q61xj_default(1d20e7af-af48-11e8-bf2f-000c29a01556)\" failed: rpc error: code = 2 desc = unable to pull sandbox image \"gcr.io/google_containers/pause-amd64:3.0\": Error response from daemon: {\"message\":\"Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\"}"
根據信息可知錯誤是由於下載這個鏡像失敗:gcr.io/google_containers/pause-amd64:3.0 。仍是網絡環境的問題,這時能夠在 dockerhub 上找到相同的鏡像下載並修改 tag 來獲得這個鏡像。
在 node 節點上執行
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
鏡像下載好以後再次查看 deployment 狀態:
kubectl get deployment # ---顯示以下--- NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE kubernetes-bootcamp 1 1 1 1 35m
此時服務已經部署正確,爲了集羣外部也可以訪問到服務,如今須要使用 NodePort 方式將端口暴露出來。
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080 kubectl get service # ---輸出以下--- NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 169.169.0.1 <none> 443/TCP 2d kubernetes-bootcamp 169.169.210.120 <nodes> 8080:10412/TCP 12m
此時 node 上的 10412 端口已經打開(這裏的 10412 端口是在 kube-apiserver 啓動參數 --service-node-port-range 範圍內隨機分配的),而且在 node 本機上是能夠訪問的。可是集羣外部訪問就會超時,包括沒有安裝 kube-proxy 的 master 訪問也會超時。解決辦法參考這裏。
爲了安全起見, docker 在 1.13 版本以後,將系統iptables 中 FORWARD 鏈的默認策略設置爲 DROP,併爲鏈接到 docker0 網橋的容器添加了放行規則。
知道了緣由是 docker 啓動時修改了iptables 規則後,能夠修改 docker 的服務文件 /lib/systemd/system/docker.service 添加下面內容
ExecStartPost=/sbin/iptables -P FORWARD ACCEPT
含義爲在啓動 docker 以後,修改 FORWARD 鏈的默認規則爲 ACCEPT。配置完成以後重啓 docker 。此時外部就能夠訪問了。
至此,一個單 master 單 node 的非安全 kubernets 集羣已經配置完成,而且基礎功能能夠正常使用。