環境規劃
手里的環境是四臺安裝了CentOS 7的主機。環境規劃如下:
Kubernetes Master 節點:192.168.20.145
Kubernetes Node 節點:192.168.20.146, 192.168.20.147
Docker私有庫節點:192.168.20.148
每臺主機上都運行了如下命令來關閉防火墻和啟用ntp:
# systemctl stop firewalld
# systemctl disable firewalld
# yum -y install ntp
# systemctl start ntpd
# systemctl enable ntpd
Kubernetes Master節點的安裝與配置
在Kubernetes Master節點上安裝etcd, docker和Kubernetes
# yum -y install etcd docker kubernetes flannel
對etcd進行配置,編輯/etc/etcd/etcd.conf,內容如下:
ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"
其中ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"表示etcd在2379端口上監聽所有網絡接口。
對Master節點上的Kubernetes進行配置,編輯配置文件/etc/kubernetes/config
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"
KUBE_MASTER="--master=http://192.168.20.145:8080"
KUBE_MASTER="--master=http://192.168.20.145:8080"是將Kubernetes的apiserver進程的服務地址告訴Kubernetes的controller-manager, scheduler和proxy進程。
編輯配置文件/etc/kubernetes/apiserver
KUBE_API_ADDRESS="--address=0.0.0.0"
KUBE_API_PORT="--port=8080"
KUBELET_PORT="--kubelet-port=10250"
KUBE_ETCD_SERVERS="--etcd-servers=http://127.0.0.1:2379"
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
KUBE_API_ARGS=""
默認配置文件是沒有去掉ServiceAccount,這里一定要去掉,不然創建pod會失敗
這些配置讓apiserver進程在8080端口上監聽所有網絡接口,并告訴apiserver進程etcd服務的地址。
對flannel進行配置,編輯/etc/sysconfig/flanneld,內容如下:
FLANNEL_ETCD="http://192.168.20.145:2379"
FLANNEL_ETCD_KEY="/atomic.io/network"
現在,啟動Kubernetes Master節點上的etcd, docker, apiserver, controller-manager和scheduler進程并查看其狀態:
# for SERVICES? in etcd docker kube-apiserver kube-controller-manager kube-scheduler flanneld;? do
systemctl restart $SERVICES
systemctl enable $SERVICES
systemctl status $SERVICES
done
在etcd里定義flannel網絡配置:
# etcdctl mk /atomic.io/network/config '{"Network":"172.17.0.0/16"}'
在隨后Kubernetes的Node節點搭建和配置時,我們可以看到,etcd里的/atomic.io/network/config節點會被Node節點上的flannel用來創建網絡的iptables
現在我們可以使用kubectl get nodes命令來查看,當然,目前還沒有Node節點加入到該Kubernetes集群,所以命令的執行結果是空的:
# kubectl get nodes
NAME? ? ? ? ? ? ? STATUS? ? AGE
Kubernetes Node節點的安裝與配置
在Kubernetes Node節點上安裝flannel, docker和Kubernetes
# yum -y install flannel docker kubernetes
對flannel進行配置,編輯/etc/sysconfig/flanneld,內容如下:
FLANNEL_ETCD="http://192.168.20.145:2379"
FLANNEL_ETCD_KEY="/atomic.io/network"
配置信息告訴flannel進程etcd服務的位置以及在etcd上網絡配置信息的節點位置
對Node節點上的Kubernetes進行配置,兩臺Node節點(192.168.20.146和192.168.20.147)上的配置文件/etc/kubernetes/config內容和Master節點(192.168.20.145)相同,內容如下:
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"
KUBE_MASTER="--master=http://192.168.20.145:8080"
KUBE_MASTER="--master=http://192.168.20.145:8080"是將Kubernetes的apiserver進程的服務地址告訴Kubernetes的controller-manager, scheduler和proxy進程。
而兩臺Node節點上的/etc/kubernetes/kubelet配置文件內容略微有點不同。
192.168.20.146節點的/etc/kubernetes/kubelet:
KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_PORT="--port=10250"
KUBELET_HOSTNAME="--hostname-override=192.168.20.146"
KUBELET_API_SERVER="--api-servers=http://192.168.20.145:8080"
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
KUBELET_ARGS=""
192.168.20.147節點的/etc/kubernetes/kubelet:
KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_PORT="--port=10250"
KUBELET_HOSTNAME="--hostname-override=192.168.20.147"
KUBELET_API_SERVER="--api-servers=http://192.168.20.145:8080"
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
KUBELET_ARGS=""
分別在兩個Kubernetes Node節點上啟動kube-proxy kubelet docker和flanneld進程并查看其狀態:
# for SERVICES in kube-proxy kubelet docker flanneld; do
systemctl restart $SERVICES
systemctl enable $SERVICES
systemctl status $SERVICES
done
現在我們在Master節點上使用kubectl get nodes命令來查看,可以看到加入的兩個Node節點:
# kubectl get nodes
NAME? ? ? ? ? ? ? STATUS? ? AGE
192.168.20.146? Ready? ? 2d
192.168.20.147? Ready? ? 2d
至此,Kubernetes集群環境搭建完畢,但是我的故事還沒有結束。
Docker私有庫搭建
搭建完了Kubernetes集群環境,我滿心歡喜地去創建Pods,失敗了。用kubectl describe和kubectl logs命令定位原因,發現原因是我的集群環境無法從gcr.io(Google Container-Registry)拉取鏡像,但是從Docker hub可以拉取鏡像。所以我萌生了搭建一個Docker私有鏡像的想法。查閱資料后,過程描述如下。
為了讓Docker私有庫更加安全,我生成了自簽名的證書來配置TLS. 首先編輯/etc/pki/tls/openssl.cnf,在[ v3_ca ]下增加了一行:
[plain]view plaincopy
[ v3_ca ]
subjectAltName = IP:192.168.20.148
然后使用openssl命令在當前的certs目錄下創建了一個自簽名的證書:
# mkdir -p certs && openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt
在證書的創建過程中,會詢問國家、省分、城市、組織、部門和common name的信息,其中common name信息我填寫的是主機的IP 192.168.20.148. 證書創建完畢后,在certs目錄下出現了兩個文件:證書文件domain.crt和私鑰文件domain.key
在192.168.20.148上安裝docker
# yum -y install docker
將前面生成的domain.crt文件復制到/etc/docker/certs.d/192.168.20.148:5000目錄下,然后重啟docker進程:
# mkdir -p /etc/docker/certs.d/192.168.20.148:5000
# cp certs/domain.crt /etc/docker/certs.d/192.168.20.148:5000/ca.crt
# systemctl restart docker
在Docker私有庫節點192.168.20.148上運行registry容器,并暴露容器的5000端口:
# docker run -d -p 5000:5000 --restart=always --name registry? -v `pwd`/certs:/certs? -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt? -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key? registry:2
最后,將domain.crt文件復制到Kubernetes集群里的所有節點的/etc/docker/certs.d/192.168.20.148:5000目錄下,并重啟各節點的docker進程,例如在192.168.169.121節點上運行:
# mkdir -p /etc/docker/certs.d/192.168.20.148:5000
# scp root@192.168.20.148:~/certs/domain.crt /etc/docker/certs.d/192.168.20.148:5000/ca.crt
# systemctl restart docker
至此,Docker私有庫搭建完成。
Kubernetes Web UI搭建
這節我以搭建Kubernetes Web UI(kubernetes-dashboard)來簡要演示如何使用Docker私有庫。
由于gcr.io被墻,我的Kubernetes集群無法直接從gcr.io拉取kubernetes-dashboard的鏡像,我事先從docker.io下載了下載地址docker.io/mritd/kubernetes-dashboard-amd64:
# docker pull mritd/kubernetes-dashboard-amd64
# docker images
REPOSITORY? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TAG? ? ? ? ? ? ? ? IMAGE ID? ? ? ? ? ? CREATED? ? ? ? ? ? SIZE
registry? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2? ? ? ? ? ? ? ? ? c6c14b3960bd? ? ? ? 3 days ago? ? ? ? ? 33.28 MB
ubuntu? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? latest? ? ? ? ? ? ? 42118e3df429? ? ? ? 9 days ago? ? ? ? ? 124.8 MB
hello-world? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? latest? ? ? ? ? ? ? c54a2cc56cbb? ? ? ? 4 weeks ago? ? ? ? 1.848 kB
docker.io/mritd/kubernetes-dashboard-amd64? ? ? v1.1.0? ? ? ? ? ? ? 20b7531358be? ? ? ? 5 weeks ago? ? ? ? 58.52 MB
registry? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2? ? ? ? ? ? ? ? ? 8ff6a4aae657? ? ? ? 7 weeks ago? ? ? ? 171.5 MB
我為加載的kubernetes-dashboard鏡像打上私有庫的標簽并推送到私有庫:
# docker tag 20b7531358be 192.168.20.148:5000/kubernetes-dashboard-amd64
# docker push 192.168.20.148:5000/kubernetes-dashboard-amd64
kubernetes-dashboard.yaml配置文件如下,因為最新版本是1.7變化很大,所以這里用1.5的配置文件代替,對其進行編輯如下:
# Copyright 2015 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#? ? http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Configuration to deploy release version of the Dashboard UI.
#
# Example usage: kubectl create -f
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
labels:
app: kubernetes-dashboard
version: v1.1.0
name: kubernetes-dashboard
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: kubernetes-dashboard
template:
metadata:
labels:
app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: 192.168.20.148:5000/kubernetes-dashboard-amd64
imagePullPolicy: Always
ports:
- containerPort: 9090
protocol: TCP
args:
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
- --apiserver-host=192.168.20.145:8080
livenessProbe:
httpGet:
path: /
port: 9090
initialDelaySeconds: 30
timeoutSeconds: 30
---
kind: Service
apiVersion: v1
metadata:
labels:
app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
type: NodePort
ports:
- port: 80
targetPort: 9090
selector:
app: kubernetes-dashboard
尤其要注意:1 創建的Pods所要拉取的鏡像是Docker私有庫的192.168.20.148:5000/kubernetes-dashboard-adm64; 2 apiserver-host參數是192.168.20.145:8080,即Kubernetes Master節點的aipserver服務地址。
修改完kubernetes-dashboard.yaml后保存到Kubernetes Master節點192.168.20.145節點上,在該節點上用kubectl create命令創建kubernetes-dashboard:
# kubectl create -f kubernetes-dashboard.yaml
創建完成后,查看Pods和Service的詳細信息:
# kubectl get pods --all-namespaces
NAMESPACE? ? NAME? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? READY? ? STATUS? ? RESTARTS? AGE
default? ? ? nginx? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1/1? ? ? Running? 0? ? ? ? ? 3h
kube-system? kubernetes-dashboard-4164430742-lqhcg? 1/1? ? ? Running? 0? ? ? ? ? 2h
# kubectl describe pods/kubernetes-dashboard-4164430742-lqhcg --namespace="kube-system"
Name:? ? ? ? kubernetes-dashboard-4164430742-lqhcg
Namespace:? ? kube-system
Node:? ? ? ? 192.168.20.146/192.168.20.146
Start Time:? ? Mon, 01 Aug 2016 16:12:02 +0800
Labels:? ? ? ? app=kubernetes-dashboard,pod-template-hash=4164430742
Status:? ? ? ? Running
IP:? ? ? ? 172.17.17.3
Controllers:? ? ReplicaSet/kubernetes-dashboard-4164430742
Containers:
kubernetes-dashboard:
Container ID:? ? docker://40ab377c5b8a333487f251547e5de51af63570c31f9ba05fe3030a02cbb3660c
Image:? ? ? ? 192.168.20.148:5000/kubernetes-dashboard-amd64
Image ID:? ? ? ? docker://sha256:20b7531358be693a34eafdedee2954f381a95db469457667afd4ceeb7146cd1f
Port:? ? ? ? 9090/TCP
Args:
--apiserver-host=192.168.20.145:8080
QoS Tier:
cpu:? ? ? ? BestEffort
memory:? ? ? ? BestEffort
State:? ? ? ? Running
Started:? ? ? ? Mon, 01 Aug 2016 16:12:03 +0800
Ready:? ? ? ? True
Restart Count:? ? 0
Liveness:? ? ? ? http-get http://:9090/ delay=30s timeout=30s period=10s #success=1 #failure=3
Environment Variables:
Conditions:
Type? ? ? ? Status
Ready? ? True
No volumes.
No events.
# kubectl describe service/kubernetes-dashboard --namespace="kube-system"
Name:? ? ? ? ? ? kubernetes-dashboard
Namespace:? ? ? ? kube-system
Labels:? ? ? ? ? ? app=kubernetes-dashboard
Selector:? ? ? ? app=kubernetes-dashboard
Type:? ? ? ? ? ? NodePort
IP:? ? ? ? ? ? 10.254.213.209
Port:? ? ? ? ? ? ? ? 80/TCP
NodePort:? ? ? ? ? ? 31482/TCP
Endpoints:? ? ? ? 172.17.17.3:9090
Session Affinity:? ? None
No events.
從kubernetes-dashboard的service詳細信息可以看到,該service綁定到了Node節點的31482端口上?,F在,通過瀏覽器訪問該端口就能看到Kubernetes的Web UI,地址:192.168.20.145:8080/ui會自動進行跳轉: