在github下载最新的kuberbetes二进制包,这里我下载的是v1.2.4的版本。
tar zxvf kubernetes.tar.gz
cd kubernetes
// 解压amd64的版本
tar zxvf kubernetes/server/kubernetes-server-linux-amd64.tar.gz
cd kubernetes/server/kubernetes/server/bin
// 将下列文件复制到各个节点上
cp kube-apiserver kube-proxy kubelet kube-scheduler kube-controller-manager /opt/bin
将kube-apiserver kube-proxy kubelet kube-scheduler kube-controller-manager复制到各个节点上,我这里放到各个节点到/opt/bin
文件夹里
可以参考前文。确保etcdctl命令可用。在这里我用etcd2代替etcd
由于每个节点docker容器的ip可能是相同的,为了使不同节点上的docker容器能够互相连接,所以需要有一种方法来统一分配每个节点的docker容器ip,防止冲突,并提供不同节点容器的连接能力,也就是SDN(software defined network) kubernetes没有提供这个功能,不过有许多的kubernetes社区有许多解决方案。如flannel
,calico
, OVS
等
这里我选用CoreOS的flannel
flannel使用etcd来保存子网ip等分配,新加入节点的flanned通过访问etcd来获取一个可用的子网网段,并负责容器间的代理转发。
在CoreOS中自带flannel.service,但实际上CoreOS为了节省空间,这个service实际上是运行了一个flannel的docker容器,第一次启动时需要从网络下载flannel的镜像。由于众所周知的原因,我们还是下载编译好的二进制包吧。
在https://github.com/coreos/flannel下载最新的release,解压出flanneld,同样放入/opt/bin
里
在所有节点/etc/systemd/system/*.service
里添加flannel.service
文件
[Unit]
Description=Flannel network fabric for CoreOS
Requires=etcd2.service
After=etcd2.service
[Service]
EnvironmentFile=/etc/environment
ExecStartPre=-/bin/bash -c "until /usr/bin/etcdctl set /coreos.com/network/config '{\"Network\": \"10.100.0.0/16\"}'; do echo \"waiting for etcd to become available...\"; sleep 5; done"
ExecStart=/opt/bin/flanneld -iface=$private_ipv4
ExecStartPost=-/bin/bash -c "until [ -e /run/flannel/subnet.env ]; do echo \"waiting for write.\"; sleep 3; done"
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
flanneld成功获取到子网网段后会以环境变量的形式保存在/run/flannel/subnet.env
文件里。我们再修改docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
After=docker.socket early-docker.target network.target flannel.service
Requires=docker.socket early-docker.target flannel.service
[Service]
Environment="DOCKER_CGROUPS=--exec-opt native.cgroupdriver=systemd"
EnvironmentFile=/run/flannel/subnet.env
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
ExecStartPre=-/usr/bin/ip link set dev docker0 down
ExecStartPre=-/usr/sbin/brctl delbr docker0
ExecStart=/usr/lib/coreos/dockerd daemon --host=fd:// $DOCKER_OPTS $DOCKER_CGROU --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU} $DOCKER_OPTS
[Install]
WantedBy=multi-user.target
使用subnet.env中的参数启动docker service, 保证不同节点的docker容器网段不同。
etcd和网络配置好了以后后面的就没什么的了。
在/etc/systemd/system/*.service
下创建systemd服务文件方便我们管理这些服务
在master节点创建
kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
Requires=etcd2.service
After=etcd2.service
[Service]
ExecStart=/opt/bin/kube-apiserver \
--allow-privileged=true \
--etcd-servers=http://$private_ipv4:2379 \
--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota \
--insecure-bind-address=0.0.0.0 \
--advertise-address=$private_ipv4 \
--service-cluster-ip-range=10.100.0.0/16 \
--runtime-config=extensions/v1beta1/daemonsets=true,extensions/v1beta1/deployments=true,extensions/v1beta1/ingress=true \
--logtostderr=true
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
Requires=kube-apiserver.service
After=kube-apiserver.service
[Service]
ExecStart=/opt/bin/kube-controller-manager \
--master=$private_ipv4:8080 \
--logtostderr=true
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
Requires=kube-apiserver.service
After=kube-apiserver.service
[Service]
ExecStart=/opt/bin/kube-scheduler --master=$private_ipv4:8080 --logtostderr=true
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
在node节点创建
kubelet.service
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=docker.service
Requires=docker.service
[Service]
ExecStartPre=/usr/bin/mkdir -p /etc/kubernetes/manifests
ExecStart=/opt/bin/kubelet \
--address=0.0.0.0 \
--allow-privileged=true \
--cluster-dns=10.100.0.10 \
--cluster-domain=cluster.local \
--config=/etc/kubernetes/manifests \
--hostname-override=$private_ipv4 \
--api-servers=http://<API_SERVER_IP>:8080 \
--pod-infra-container-image="kubernetes/pause" \
--network-plugin-dir=/etc/cni/net.d \
--network-plugin=cni \
--logtostderr=true
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
kube-proxy.service
Unit]
Description=Kubernetes Proxy
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
Requires=kubelet.service
After=kubelet.service
[Service]
ExecStart=/opt/bin/kube-proxy \
--master=http://<API_SERVER_IP>:8080 \
--proxy-mode=iptables \
--logtostderr=true
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
启动上面的所以service kubernetes集群应该就搭建起来了。我们来测试一下
新建一个nginx.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx:alpine
ports:
- containerPort: 80
执行
> create -f ./nginx.yaml
// 查看pod运行状况
> kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE NODE
my-nginx-2643493705-274ab 1/1 Running 0 1m 192.168.64.9
my-nginx-2643493705-8wr06 1/1 Running 0 1m 192.168.64.109
我们可以看到启动了两个nginx的pod
查看每个pod的ip
> kubectl get pods -l run=my-nginx -o yaml | grep podIP
podIP: 10.100.73.2
podIP: 10.100.63.2
我们在内任一台机上执行
> curl http://10.100.73.2
应该会看到nginx的欢迎页面打印出来。
参考资料
[1]http://qiankunli.github.io/2015/01/29/Kubernetes_installation.html
[2]https://github.com/shenshouer/calico-kubernetes
[3]http://qinghua.github.io/kubernetes-in-mesos-8/
[4]http://kubernetes.io/docs/user-guide/connecting-applications/