在上一篇筆記中,咱們已經可使用 k8s1.6 版本搭建一個基礎的集羣,在集羣內部能夠完成不一樣 node 之間的 pod 互通而且能夠完成服務發現。但已經完成的這個集羣仍然是經過不安全的 8080 端口進行的,而且除了最基本的 apiserver 和 controller-manager 之間之外,其餘組件間通信都沒有認證措施。這一次,我準備在集羣中加入 TLS 驗證來增強集羣的安全性,不過此次只加入認證並不考慮受權,同時加入 kubeconfig 配置文件的機制,將apiserver地址和一些客戶端證書存放在 kubeconfig 配置文件中。再安裝一個新的插件 Dashboard ,用於以web方式管理集羣。html
此次使用的 k8s 版本是比較新的 1.10.8 。第一個緣由是已經決定使用 kubeconfig 來進行配置因此舊版本不是必須的,另外一個緣由是在使用 tls 證書時 1.6.0 版本出現了一些 bug,因此就決定直接將 k8s 更換成比較新的版本。到目前爲止 k8s 仍在快速迭代,因此建議在使用的時候選擇新一些的版本。node
主機名 | 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 理解有些錯誤,clusterIP 是 service 使用的 IP 地址段,和 pod 使用的 ip 地址段不是同一個配置,而且應該無重合部分(與物理機IP段也不要有重合部分)。此次指定 clusterIP 端爲 10.0.0.0/16 ,kube-dns 的 service 使用的 IP 地址爲 10.0.0.10linux
準備工做基本能夠概括爲如下幾步git
設置如下內核參數,能夠在 /etc/sysctl.conf 文件或者等效的其餘文件內填寫github
net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1
部分發行版本的 linux 可能不默認加載 br_netfilter 模塊致使沒法加載後兩條規則,若是缺乏模塊須要提早配置加載,這裏不詳細介紹過程了。web
若是有內部 DNS,能夠在內部 DNS 上配置各個節點間能夠經過主機名互相解析。若是沒有則須要配置 /etc/hosts 解析各個節點,像下面這樣:docker
# 添加以下幾行 192.168.112.148 u16-1 192.168.112.149 u16-2 192.168.112.150 u16-3
$ 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 複製到系統目錄 /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 、一組客戶端證書用於其餘組件。api
# 由於此次不須要對證書配置過多的屬性,因此仍是使用上次使用的 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'.
上一步已經將須要的二進制可執行文件和證書祕鑰放在相應的位置了,下面須要建立管理腳本 /lib/systemd/system/kube-controller-manager.service 和 配置文件 /etc/kubernetes/controller-managerbash
$ 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.
二進制文件和 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.
在全部節點上操做安裝以下組件。
$ 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 中的解析對應
此部分與上一篇筆記基本相同
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
嘗試在節點間使用 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 是 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: k8s-app: kubernetes-dashboard kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: selector: k8s-app: kubernetes-dashboard ports: - port: 443 targetPort: 8443 nodePort: 31000 type: NodePort # 而後就可使用這些配置文件安裝 Dashboard 了 $ kubectl apply -f dashboard-configmap.yaml -f dashboard-secret.yaml -f dashboard-service.yaml $ kubectl apply -f dashboard-controller.yaml # 建立後查看 pod 的狀態,ready 後就能夠經過 https://NODEIP:31000 訪問。 $ kubectl get pod -n kube-system|grep dashboard kubernetes-dashboard-598d75cb96-fsrlm 1/1 Running 0 2m # 訪問 Dashboard 時會提示身份驗證,由於沒有配置權限,這時點擊跳過能夠進入 Dashboard 。或者能夠經過 token 登陸。 token 能夠經過 kubectl 查看 $ kubectl get secrets -n kube-system |grep kubernetes-dashboard-token kubernetes-dashboard-token-4s5p5 kubernetes.io/service-account-token 3 23m $ kubectl describe secrets kubernetes-dashboard-token-4s5p5 -n kube-system|grep 'token:' token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi00czVwNSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjRmYmFjMWUyLWMyMjctMTFlOC04NDk1LTAwMGMyOWEwMTU1NiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.rMNq9DbbPQc7XYl7M0We1zAWQgIHk1hlt7AXMyoE2YKCf6YIjcW96o454KEuM6LFoWY7SDQL_PRMA3keoKhDfMJtOc2Y5HOeYaxxgqkD3xrEeShEPO3fWOvaYiZU7-hemlMo_avb-YAB5VUGVFQQLYB-1bjrcII7qJj18tJu3Wd2lmqXnxYEV62ZMRUUTprEmBoTdRGyzHa0_JwD37Sjkrb0VqCLQN7n59pbOGpSxvdw5jSLoMolOnWywzVV3Ji7rFjvqHz6z2WX8sYcgEFGShHLPU8pFJo9YLc_D6F0FsDjqPyNPfW0Fv3j0zu38OHC5z896ow9Z1PP3qap2PiFdQ