一、相關准備工作
1.1、准備工作
- 准備至少兩台已安裝好CentOS7.2操作系統的物理機或者虛擬機(本文配置時使用的是三台KVM虛擬機);
- 設置hostname命令:
hostnamectl set-hostname k8s-mst
Role IP Hostname Master 192.168.3.87 k8s-mst Node 192.168.3.88 k8s-nod1 Node 192.168.3.89 k8s-nod2
- 修改所有虛擬機或者物理機的hosts文件(/etc/hosts),添加如下內容:
192.168.3.87 k8s-mst
192.168.3.88 k8s-nod1
192.168.3.89 k8s-nod2
-
為了避免和Docker的iptables產生沖突,需要關閉Node節點上的防火牆
systemctl stop firewalld
systemctl disable firewalld -
為了讓各個節點的時間保持一致,需要為所有節點安裝NTP
yum -y install ntp
systemctl start ntpd
systemctl enable ntpd
1.2、編譯Kubernetes源碼(建議在Node節點上)
1.2.1、安裝docker-engine
官方指導資料
使用以下方法可以安裝較新版本
- 添加yum庫
sudo tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/experimental/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF
-
安裝Docker-engine
sudo yum install -y docker-engine -
運行Docker Daemon
sudo systemctl start docker -
可以使用
sudo systemctl status docker查看docker Daemon的運行狀態
1.2.2、安裝Golang
sudo yum install -y golang
1.2.3、下載Kubernetes
- 從Kubernetes的github下載源碼
git clone https://github.com/kubernetes/kubernetes.git - 或者直接下載相應版本的release包https://codeload.github.com/kubernetes/kubernetes/tar.gz/v1.4.6
- 如果使用git clone,下載完成后進入kubernetes文件夾,使用命令
git checkout v1.4.6,下載release包則解壓tar -xvf kubernetes-1.4.6.tar.gz進入kubernetes文件夾;
1.2.4、編譯Kubernetes
-
修改hosts
由於在Kubernetes編譯過程中需要pull谷歌容器庫(gcr)中的相關鏡像,故需要修改hosts進行翻牆,hosts文件參考:https://github.com/racaljk/hosts -
修改運行平台配置參數
根據自己的運行平台(linux/amd64)修改hack/lib/golang.sh,把KUBE_SERVER_PLATFORMS,KUBE_CLIENT_PLATFORMS和KUBE_TEST_PLATFORMS中除linux/amd64以外的其他平台注釋掉,以此來減少編譯所用時間 -
編譯源碼
在Kubernetes根目錄下運行命令make release-skip-tests,編譯耗時相對較長 -
編譯成功之后,可執行文件在文件夾“_output”中
二、Master配置工作
2.1、安裝ectd並修改配置文件
2.1.1、安裝必要軟件etcd
yum -y install etcd
2.1.2、 修改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"
2.1.3、運行etcd
sudo systemctl enable etcd
sudo systemctl start etcd
2.1.4、配置etcd中的網絡
etcdctl mk /atomic.io/network/config '{"Network":"172.17.0.0/16"}'
2.2、kubernetes環境配置
2.2.1、復制命令(可執行文件)
將位於_output/release-stage/server/linux-amd64/kubernetes/server/bin/目錄下的kube-apiserver、kube-controller-manager、kube-scheduler、kubectl復制到Master節點的/usr/bin/目錄下
2.2.2、創建相應的service文件以及配置文件(shell腳本)
根據自己的的配置修改MASTER_ADDRESS和ETCD_SERVERS
#!/bin/bash
# Copyright 2016 The Kubernetes Authors.
#
# 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.
MASTER_ADDRESS=${1:-"192.168.3.87"}
ETCD_SERVERS=${2:-"http://192.168.3.87:2379"}
SERVICE_CLUSTER_IP_RANGE=${3:-"10.254.0.0/16"}
ADMISSION_CONTROL=${4:-"NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"}
cat <<EOF >/etc/kubernetes/config
# --logtostderr=true: log to standard error instead of files
KUBE_LOGTOSTDERR="--logtostderr=true"
# --v=0: log level for V logs
KUBE_LOG_LEVEL="--v=0"
# --allow-privileged=false: If true, allow privileged containers.
KUBE_ALLOW_PRIV="--allow-privileged=false"
# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=${MASTER_ADDRESS}:8080"
EOF
cat <<EOF >/etc/kubernetes/apiserver
# --insecure-bind-address=127.0.0.1: The IP address on which to serve the --insecure-port.
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
# --insecure-port=8080: The port on which to serve unsecured, unauthenticated access.
KUBE_API_PORT="--insecure-port=8080"
# --kubelet-port=10250: Kubelet port
NODE_PORT="--kubelet-port=10250"
# --etcd-servers=[]: List of etcd servers to watch (http://ip:port),
# comma separated. Mutually exclusive with -etcd-config
KUBE_ETCD_SERVERS="--etcd-servers=${ETCD_SERVERS}"
# --advertise-address=<nil>: The IP address on which to advertise
# the apiserver to members of the cluster.
KUBE_ADVERTISE_ADDR="--advertise-address=${MASTER_ADDRESS}"
# --service-cluster-ip-range=<nil>: A CIDR notation IP range from which to assign service cluster IPs.
# This must not overlap with any IP ranges assigned to nodes for pods.
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=${SERVICE_CLUSTER_IP_RANGE}"
# --admission-control="AlwaysAdmit": Ordered list of plug-ins
# to do admission control of resources into cluster.
# Comma-delimited list of:
# LimitRanger, AlwaysDeny, SecurityContextDeny, NamespaceExists,
# NamespaceLifecycle, NamespaceAutoProvision,
# AlwaysAdmit, ServiceAccount, ResourceQuota, DefaultStorageClass
KUBE_ADMISSION_CONTROL="--admission-control=${ADMISSION_CONTROL}"
# Add your own!
KUBE_API_ARGS=""
EOF
KUBE_APISERVER_OPTS=" \${KUBE_LOGTOSTDERR} \\
\${KUBE_LOG_LEVEL} \\
\${KUBE_ETCD_SERVERS} \\
\${KUBE_API_ADDRESS} \\
\${KUBE_API_PORT} \\
\${NODE_PORT} \\
\${KUBE_ADVERTISE_ADDR} \\
\${KUBE_ALLOW_PRIV} \\
\${KUBE_SERVICE_ADDRESSES} \\
\${KUBE_ADMISSION_CONTROL} \\
\${KUBE_API_ARGS}"
cat <<EOF >/usr/lib/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
After=etcd.service
[Service]
EnvironmentFile=-/etc/kubernetes/config
EnvironmentFile=-/etc/kubernetes/apiserver
ExecStart=/usr/bin/kube-apiserver ${KUBE_APISERVER_OPTS}
Restart=on-failure
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
cat <<EOF >/etc/kubernetes/controller-manager
###
# The following values are used to configure the kubernetes controller-manager
# defaults from config and apiserver should be adequate
# Add your own!
KUBE_CONTROLLER_MANAGER_ARGS=""
EOF
KUBE_CONTROLLER_MANAGER_OPTS=" \${KUBE_LOGTOSTDERR} \\
\${KUBE_LOG_LEVEL} \\
\${KUBE_MASTER} \\
\${KUBE_CONTROLLER_MANAGER_ARGS}"
cat <<EOF >/usr/lib/systemd/system/kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/etc/kubernetes/config
EnvironmentFile=-/etc/kubernetes/controller-manager
ExecStart=/usr/bin/kube-controller-manager ${KUBE_CONTROLLER_MANAGER_OPTS}
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
cat <<EOF >/etc/kubernetes/scheduler
###
# kubernetes scheduler config
# Add your own!
KUBE_SCHEDULER_ARGS=""
EOF
KUBE_SCHEDULER_OPTS=" \${KUBE_LOGTOSTDERR} \\
\${KUBE_LOG_LEVEL} \\
\${KUBE_MASTER} \\
\${KUBE_SCHEDULER_ARGS}"
cat <<EOF >/usr/lib/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/etc/kubernetes/config
EnvironmentFile=-/etc/kubernetes/scheduler
ExecStart=/usr/bin/kube-scheduler ${KUBE_SCHEDULER_OPTS}
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
2.2.3、運行相應的Kubernetes命令(shell 腳本)
for svc in kube-apiserver kube-controller-manager kube-scheduler; do
systemctl restart $svc
systemctl enable $svc
systemctl status $svc
done
三、Node配置工作
3.1、安裝flannel並修改配置文件
3.1.1、安裝必要軟件flannel
yum -y install flannel
3.1.2、 修改flannel的配置文件/etc/sysconfig/flanneld
FLANNEL_ETCD="http://192.168.3.87:2379"
FLANNEL_ETCD_KEY="/atomic.io/network"
3.1.3、運行flannel
systemctl restart flanneld
systemctl enable flanneld
systemctl status flanneld
3.1.4、上傳網絡配置
創建一個config.json文件,內容如下:
{
"Network": "172.17.0.0/16",
"SubnetLen": 24,
"Backend": {
"Type": "vxlan",
"VNI": 7890
}
}
然后將配置上傳到etcd服務器上:
curl -L http://192.168.3.87:2379/v2/keys/atomic.io/network/config -XPUT --data-urlencode value@config.json
3.2、kubernetes環境配置
3.2.1、復制命令(可執行文件)
將位於_output/release-stage/server/linux-amd64/kubernetes/server/bin/目錄下的kube-proxy、kubelet 復制到Node節點的/usr/bin/目錄下
3.2.2、創建相應的service文件以及配置文件(shell腳本)
根據自己的的配置修改MASTER_ADDRESS和NODE_HOSTNAME
#!/bin/bash
# Copyright 2016 The Kubernetes Authors.
#
# 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.
MASTER_ADDRESS=${1:-"192.168.3.87"}
NODE_HOSTNAME=${2:-"k8s-nod"}
cat <<EOF >/etc/kubernetes/config
# --logtostderr=true: log to standard error instead of files
KUBE_LOGTOSTDERR="--logtostderr=true"
# --v=0: log level for V logs
KUBE_LOG_LEVEL="--v=0"
# --allow-privileged=false: If true, allow privileged containers.
KUBE_ALLOW_PRIV="--allow-privileged=false"
# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=${MASTER_ADDRESS}:8080"
EOF
cat <<EOF >/etc/kubernetes/proxy
###
# kubernetes proxy config
# default config should be adequate
# Add your own!
KUBE_PROXY_ARGS=""
EOF
KUBE_PROXY_OPTS=" \${KUBE_LOGTOSTDERR} \\
\${KUBE_LOG_LEVEL} \\
\${KUBE_MASTER} \\
\${KUBE_PROXY_ARGS}"
cat <<EOF >/usr/lib/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
EnvironmentFile=-/etc/kubernetes/config
EnvironmentFile=-/etc/kubernetes/kube-proxy
ExecStart=/usr/bin/kube-proxy ${KUBE_PROXY_OPTS}
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
cat <<EOF >/etc/kubernetes/kubelet
# --address=0.0.0.0: The IP address for the Kubelet to serve on (set to 0.0.0.0 for all interfaces)
KUBELET__ADDRESS="--address=0.0.0.0"
# --port=10250: The port for the Kubelet to serve on. Note that "kubectl logs" will not work if you set this flag.
KUBELET_PORT="--port=10250"
# --hostname-override="": If non-empty, will use this string as identification instead of the actual hostname.
KUBELET_HOSTNAME="--hostname-override=${NODE_HOSTNAME}"
# --api-servers=[]: List of Kubernetes API servers for publishing events,
# and reading pods and services. (ip:port), comma separated.
KUBELET_API_SERVER="--api-servers=http://${MASTER_ADDRESS}:8080"
# pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
# Add your own!
KUBELET_ARGS=""
EOF
KUBE_PROXY_OPTS=" \${KUBE_LOGTOSTDERR} \\
\${KUBE_LOG_LEVEL} \\
\${KUBELET__ADDRESS} \\
\${KUBELET_PORT} \\
\${KUBELET_HOSTNAME} \\
\${KUBELET_API_SERVER} \\
\${KUBE_ALLOW_PRIV} \\
\${KUBELET_POD_INFRA_CONTAINER}\\
\${KUBELET_ARGS}"
cat <<EOF >/usr/lib/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
EnvironmentFile=-/etc/kubernetes/config
EnvironmentFile=-/etc/kubernetes/kubelet
ExecStart=/usr/bin/kubelet ${KUBE_PROXY_OPTS}
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
3.2.3、運行相應的Kubernetes命令(shell腳本)
for svc in docker kubelet kube-proxy; do
systemctl restart $svc
systemctl enable $svc
systemctl status $svc
done
如果出現以下情形:
● kubelet.service - Kubernetes Kubelet
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Active: activating (auto-restart) (Result: exit-code) since Thu 2016-12-01 17:25:42 CST; 112ms ago
Main PID: 13311 (code=exited, status=200/CHDIR)
Dec 01 17:25:42 k8s systemd[1]: Unit kubelet.service entered failed state.
Dec 01 17:25:42 k8s systemd[1]: kubelet.service failed.
是因為不存在工作目錄/var/lib/kubelet,創建相應目錄即可。
四、驗證配置以及創建dashboard
4.1、驗證環境配置
在Master節點運行命令kubectl get nodes,輸出信息如下:
[root@k8s-mst ~]# kubectl get nodes
NAME STATUS AGE
nod1 Ready 3h
nod2 Ready 3h
4.2、搭建dashboard
4.2.1、創建命名空間(namespace)kube-system
創建文件kubernetes-namespace.jason,內容如下:
{
"kind": "Namespace",
"apiVersion": "v1",
"metadata": {
"name": "kube-system"
}
}
使用命令kubectl create -f kubernetes-namespace.jason創建kube-system命名空間。
4.2.2、創建dashboard
創建kubernetes-dashboard.yaml文件
# Configuration to deploy release version of the Dashboard UI.
# Example usage: kubectl create -f <this_file>
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
labels:
app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: kubernetes-dashboard
template:
metadata:
labels:
app: kubernetes-dashboard
# Comment the following annotaion if Dashboard must not be deployed on master
annotations:
scheduler.alpha.kubernetes.io/tolerations: |
[
{
"key": "dedicated",
"operator": "Equal",
"value": "master",
"effect": "NoSchedule"
}
]
spec:
containers:
- name: kubernetes-dashboard
image: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.4.2
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=http://192.168.3.87: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
注意:
- 修改 --apiserver-host=http://192.168.3.87:8080;
- 其中 “ image: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.4.2 ”,使用的是谷歌鏡像庫,需要Node節點翻牆才會可能正常創建。
-
使用命令
kubectl create -f kubernetes-dashboard.yaml創建kubernetes-dashboard Deployment和Service。 -
如無法獲取相應的鏡像創建之后,使用命令
kubectl get pod --namespace="kube-system"查看會顯示如下結果:
[root@mst ~]# kubectl get pod --namespace="kube-system"
NAME READY STATUS RESTARTS AGE
kubernetes-dashboard-47291540-lcuox 0/1 ErrImagePull 0 1m
- 搭建自己的鏡像庫,可參考【Docker實戰】Registry & Portus搭建詳解 - 龍隱 - 博客園 http://www.cnblogs.com/xcloudbiz/articles/5497037.html
4.2.3、使用dashboard
成功運行之后:
[root@k8s-mst ~]# kubectl get pod --namespace="kube-system"
NAME READY STATUS RESTARTS AGE
kubernetes-dashboard-3856900779-226mr 1/1 Running 0 2m
[root@k8s-mst ~]# kubectl describe pod kubernetes-dashboard-3856900779-226mr --namespace="kube-system"
Name: kubernetes-dashboard-3856900779-226mr
Namespace: kube-system
Node: nod1/192.168.3.91
Start Time: Tue, 22 Nov 2016 20:33:04 +0800
Labels: app=kubernetes-dashboard
pod-template-hash=3856900779
Status: Running
IP: 172.18.0.2
Controllers: ReplicaSet/kubernetes-dashboard-3856900779
Containers:
kubernetes-dashboard:
Container ID: docker://d36cff522129c73f0de370857124697659662c99d370af548a1367604bac7014
Image: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.4.2
Image ID: docker://sha256:c0e4ba8968ee756368cbe5f64f39b0ef8e128de90d0bdfe1d040f0773055e68a
Port: 9090/TCP
Args:
--apiserver-host=http://192.168.3.87:8080
State: Running
Started: Tue, 22 Nov 2016 20:35:00 +0800
Ready: True
Restart Count: 0
Liveness: http-get http://:9090/ delay=30s timeout=30s period=10s #success=1 #failure=3
Volume Mounts: <none>
Environment Variables: <none>
Conditions:
Type Status
Initialized True
Ready True
PodScheduled True
No volumes.
QoS Class: BestEffort
Tolerations: dedicated=master:Equal:NoSchedule
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
4m 4m 1 {default-scheduler } Normal Scheduled Successfully assigned kubernetes-dashboard-3856900779-226mr to nod1
3m 3m 1 {kubelet nod1} spec.containers{kubernetes-dashboard} Normal Pulling pulling image "gcr.io/google_containers/kubernetes-dashboard-amd64:v1.4.2"
3m 2m 2 {kubelet nod1} Warning MissingClusterDNS kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy.
2m 2m 1 {kubelet nod1} spec.containers{kubernetes-dashboard} Normal Pulled Successfully pulled image "gcr.io/google_containers/kubernetes-dashboard-amd64:v1.4.2"
2m 2m 1 {kubelet nod1} spec.containers{kubernetes-dashboard} Normal Created Created container with docker id d36cff522129; Security:[seccomp=unconfined]
2m 2m 1 {kubelet nod1} spec.containers{kubernetes-dashboard} Normal Started Started container with docker id d36cff522129
[root@mst ~]# 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.196.154
External IPs: 192.168.3.87
Port: <unset> 80/TCP
NodePort: <unset> 31437/TCP
Endpoints: 172.18.0.2:9090
Session Affinity: None
成功運行之后,就可以使用瀏覽器訪問192.168.3.87:8080/ui/使用dashboard。
