Docker的流行激活了一直不温不火的 PaaS,随之而来的是各类 Micro-PaaS的出现,Kubernetes是其中最具代表性的一员,它是 Google多年大规模容器管理技术的开源版本。越来越多的企业被迫面对互联网规模所带来的各类难题,而 Kubernetes以其优秀的理念和设计正在逐步形成新的技术标准,对于任何领域的运营总监、架构师和软件工程师来说,都是一个绝佳的突破机会。
准备工作 etcd下载:https://github.com/coreos/etcd/releases flannel下载:https://github.com/coreos/flannel/releases docker下载:https://github.com/docker/docker/releases kubernetes下载:https://github.com/kubernetes/kubernetes/releases
三台centos主机 k8s master: 10.11.151.97 tc-151-97 k8s node1: 10.11.151.100 tc-151-100 k8s node2: 10.11.151.101 tc-151-101
ETCD集群部署 ETCD是k8s集群的基础,可以单结点也可以以集群的方式部署。本文以三台主机组成ETCD集群进行部署,以service形式启动。在三台主机上分别执行如下操作
创建工作目录 解压ETCD安装包并将etcd和etcdctl复制到工作目录下(本文工作目录为/opt/domeos/openxxs/k8s-1.1.3-flannel)。
创建Service 创建 /lib/systemd/system/etcd.service 文件,该文件为centos系统的服务文件,注意配置其中的etcd可执行文件的绝对路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [Unit] Description=ETCD [Service] Type=notify EnvironmentFile=/etc/sysconfig/etcd ExecStart=/opt/domeos/openxxs/k8s-1.1.3-flannel/etcd $ETCD_NAME \ $INITIAL_ADVERTISE_PEER_URLS \ $LISTEN_PEER_URLS \ $ADVERTISE_CLIENT_URLS \ $LISTEN_CLIENT_URLS \ $INITIAL_CLUSTER_TOKEN \ $INITIAL_CLUSTER \ $INITIAL_CLUSTER_STATE \ $ETCD_OPTS Restart=on-failure
设置配置文件 创建 /etc/sysconfig/etcd 文件,该文件为服务的配置文件,三台主机的ETCD_NAME、INITIAL_ADVERTISE_PEER_URLS和ADVERTISE_CLIENT_URLS参数各不相同,下面为97机上的配置文件,100和101上要做相应修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ETCD_NAME='-name k8sETCD0' INITIAL_ADVERTISE_PEER_URLS='-initial-advertise-peer-urls http://10.11.151.97:4010' LISTEN_PEER_URLS='-listen-peer-urls http://0.0.0.0:4010' ADVERTISE_CLIENT_URLS='-advertise-client-urls http://10.11.151.97:4011,http://10.11.151.97:4012' LISTEN_CLIENT_URLS='-listen-client-urls http://0.0.0.0:4011,http://0.0.0.0:4012' INITIAL_CLUSTER_TOKEN='-initial-cluster-token k8s-etcd-cluster' INITIAL_CLUSTER='-initial-cluster k8sETCD0=http://10.11.151.97:4010,k8sETCD1=http://10.11.151.100:4010,k8sETCD2=http://10.11.151.101:4010' INITIAL_CLUSTER_STATE='-initial-cluster-state new' ETCD_OPTS=''
配置网络环境 启动集群前如果网络环境配置存在冲突,特别是iptables规则的干涉,会导致集群工作不正常。因此在启动前需要确认如下配置
1 systemctl stop firewalld.service
修改hosts kubelet 是通过/etc/hosts来获取本机IP的,因此需要在/etc/hosts中配置hostname和IP的对应关系,如97机上的 /etc/hosts 中需要存在这条记录 1 2 3 4 5 6 7 10.11.151.97 tc-151-97
启动Etcd 启动ETCD集群
1 2 systemctl daemon-reload systemctl start etcd
测试Etcd 1 2 3 4 5 6 7 8 9 10 systemctl status -l etcd curl -L http://10.11.151.97:4012/version curl -L http://10.11.151.100:4012/version curl -L http://10.11.151.101:4012/version
安装Kubernetes Master k8s-master一般包括三个组件:kube-apiserver、kube-controller-manager 和 kube-scheduler。如果要将k8s-master所在的主机也加入集群管理中,比如让这台主机可以使用集群内的DNS服务等,则需要在这台主机上启动kube-proxy,本文不考虑这种情况。将安装包解压后,复制 解压目录/bin/linux/amd64/ 下的 kube-apiserver、kube-controller-manager 和 kube-scheduler 到工作目录中。
创建kube-apiserver.Service /lib/systemd/system/kube-apiserver.service 文件,同样需要注意将kube-apiserver可执行文件的绝对路径配置一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [Unit] Description=kube-apiserver [Service] EnvironmentFile=/etc/sysconfig/kube-apiserver ExecStart=/opt/domeos/openxxs/k8s-1.1.3-flannel/kube-apiserver $ETCD_SERVERS \ $LOG_DIR \ $SERVICE_CLUSTER_IP_RANGE \ $INSECURE_BIND_ADDRESS \ $INSECURE_PORT \ $BIND_ADDRESS \ $SECURE_PORT \ $AUTHORIZATION_MODE \ $AUTHORIZATION_FILE \ $BASIC_AUTH_FILE \ $KUBE_APISERVER_OPTS Restart=on-failure
设置kube-apiserver配置文件 事实上只要配置了ETCD_SERVERS一项其它全留空也足以让kube-apiserver正常跑起来了。ETCD_SERVERS也并不需要将ETCD集群的所有结点服务地址写上,但至少要有一个。
如果不需要使用 https 进行认证和授权,则可以不配置BIND_ADDRESS、SECURE_PORT、AUTHORIZATION_MODE、AUTHORIZATION_FILE和BASIC_AUTH_FILE。关于安全认证和授权在k8s官方文档里给出了很详细的介绍(authorization 戳这里 ,authentication 戳这里 ),本文的配置方式以ABAC(用户配置认证策略)进行认证,同时明文存储了密码。两个配置文件的内容如下
1 2 3 4 5 {"user" : "admin" } admin,admin,adminID
/etc/sysconfig/kube-apiserver 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ETCD_SERVERS='--etcd-servers=http://10.11.151.97:4012,http://10.11.151.100:4012,http://10.11.151.101:4012' LOG_DIR='/opt/domeos/openxxs/k8s-1.1.3-flannel/logs' SERVICE_CLUSTER_IP_RANGE='--service-cluster-ip-range=172.16.0.0/16' INSECURE_BIND_ADDRESS='--insecure-bind-address=0.0.0.0' INSECURE_PORT='--insecure-port=8080' BIND_ADDRESS='--bind-address=0.0.0.0' SECURE_PORT='--secure-port=6443' AUTHORIZATION_MODE='--authorization-mode=ABAC' AUTHORIZATION_FILE='--authorization-policy-file=/opt/domeos/openxxs/k8s-1.1.3-flannel/authorization' BASIC_AUTH_FILE='--basic-auth-file=/opt/domeos/openxxs/k8s-1.1.3-flannel/authentication.csv' KUBE_APISERVER_OPTS=''
创建kube-service /lib/systemd/system/kube-controller.service 文件
1 2 3 4 5 6 7 8 9 10 11 12 [Unit] Description=kube-controller-manager After=kube-apiserver.service Wants=kube-apiserver.service [Service] EnvironmentFile=/etc/sysconfig/kube-controller ExecStart=/opt/domeos/openxxs/k8s-1.1.3-flannel/kube-controller-manager $KUBE_MASTER \ $LOG_DIR \ $CLOUD_PROVIDER \ $KUBE_CONTROLLER_OPTS Restart=on-failure
设置kube-contr配置文件 /etc/sysconfig/kube-controller 文件
1 2 3 4 5 6 7 8 9 10 KUBE_MASTER='--master=http://10.11.151.97:8080' LOG_DIR='--log-dir=/opt/domeos/openxxs/k8s-1.1.3-flannel/logs' CLOUD_PROVIDER='--cloud-provider=' KUBE_CONTROLLER_OPTS=''
创建kube-sch.Service /lib/systemd/system/kube-scheduler.service 文件
1 2 3 4 5 6 7 8 9 10 11 [Unit] Description=kube-scheduler After=kube-apiserver.service Wants=kube-apiserver.service [Service] EnvironmentFile=/etc/sysconfig/kube-scheduler ExecStart=/opt/domeos/openxxs/k8s-1.1.3-flannel/kube-scheduler $KUBE_MASTER \ $LOG_DIR \ $KUBE_SCHEDULER_OPTS Restart=on-failure
设置kube-scheduler配置文件 /etc/sysconfig/kube-scheduler 文件
1 2 3 4 5 6 7 8 KUBE_MASTER='--master=http://10.11.151.97:8080' LOG_DIR='--log-dir=/opt/domeos/openxxs/k8s-1.1.3-flannel/logs' KUBE_SCHEDULER_OPTS=''
启动KubMaster 三个组件启动是有顺序,必须等kube-apiserver正常启动之后再启动kube-controller-manager然后再启动kube-scheduler。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 systemctl daemon-reload systemctl start kube-apiserver systemctl status -l kube-apiserver curl -L http://10.11.151.97:8080/healthz systemctl daemon-reload systemctl start kube-controller systemctl status -l kube-controller systemctl daemon-reload systemctl start kube-scheduler systemctl status -l kube-scheduler
安装KubNode flannel配置写入Etcd 集群中flannel的可用子网段和网络包封装方式等配置信息需要提前写入ETCD中
写入ETCD中的key为 /flannel/network/config ,后面配置flannel服务时需要用到。配置项中的 Network 为整个k8s集群可用的子网段;SubnetLen为每个Node结点的子网掩码长度;Type表示封包的方式,推荐使用vxlan,此外还有udp等方式。
1 curl -L http://10.11.151.97:4012/v2/keys/flannel/network/config -XPUT -d value="{\"Network\":\"172.16.0.0/16\",\"SubnetLen\":25,\"Backend\":{\"Type\":\"vxlan\",\"VNI\":1}}"
安装Docker 修改配置文件 /etc/sysconfig/docker,有可能不在这个目录,可以去/etc下面找一下
1 2 3 4 5 yum install docker DOCKER_OPTS="-g /opt/domeos/openxxs/k8s-1.1.3-flannel/docker" INSECURE_REGISTRY="--insecure-registry 10.11.150.76:5000"
安装flannel 这里需要特别注意,如果对机子的网卡进行了一些修改,用于连接外网的网卡名比较特殊(比如机子用的是万兆网卡,网卡名即为p6p1),启动flannel时会报”Failed to get default interface: Unable to find default route”错误,则FLANNEL_OPTIONS需要添加参数:iface=<用于连接的网卡名>。例如100机的网卡名为em1则 iface=em1;万兆网卡的网卡名为p6p1则 iface=p6p1。
修改配置文件 /etc/sysconfig/flanneld,有可能不在这个目录,可以去/etc下面找一下
1 2 3 4 5 6 yum install flanneld FLANNEL_ETCD="http://10.11.151.97:4012" FLANNEL_ETCD_KEY="/flannel/network" FLANNEL_OPTIONS="-iface=em1"
创建kube-proxy.service /lib/systemd/system/kube-proxy.service 文件
1 2 3 4 5 6 7 8 9 10 [Unit] Description=kube-proxy [Service] EnvironmentFile=/etc/sysconfig/kube-proxy ExecStart=/opt/domeos/openxxs/k8s-1.1.3-flannel/kube-proxy $KUBE_MASTER \ $PROXY_MODE \ $LOG_DIR \ $KUBE_PROXY_OPTS Restart=on-failure
设置kube-proxy配置文件 /etc/sysconfig/kube-proxy 文件
1 2 3 4 5 6 7 8 9 10 KUBE_MASTER='--master=http://10.11.151.97:8080' PROXY_MODE='--proxy-mode=iptables' LOG_DIR='--log-dir=/opt/domeos/openxxs/k8s-1.1.3-flannel/logs' KUBE_PROXY_OPTS=''
创建kubelet.service /lib/systemd/system/kubelet.service 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [Unit] Description=kubelet [Service] EnvironmentFile=/etc/sysconfig/kubelet ExecStart=/opt/domeos/openxxs/k8s-1.1.3-flannel/kubelet $API_SERVERS \ $ADDRESS \ $HOSTNAME_OVERRIDE \ $ALLOW_PRIVILEGED \ $POD_INFRA \ $CLUSTER_DNS \ $CLUSTER_DOMAIN \ $MAX_PODS \ $LOG_DIR \ $KUBELET_OPTS Restart=on-failure
设置kubelet配置文件 /etc/sysconfig/kubelet 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 API_SERVERS='--api-servers=http://10.11.151.97:8080' ADDRESS='--address=0.0.0.0' HOSTNAME_OVERRIDE='' ALLOW_PRIVILEGED='--allow-privileged=false' POD_INFRA='--pod-infra-container-image=10.11.150.76:5000/kubernetes/pause:latest' CLUSTER_DNS='--cluster-dns=172.16.40.1' CLUSTER_DOMAIN='--cluster-domain=domeos.sohu' MAX_PODS='--max-pods=70' LOG_DIR='--log-dir=/opt/domeos/openxxs/k8s-1.1.3-flannel/logs' KUBELET_OPTS=''
这里的 CLUSTER_DNS 和 CLUSTER_DOMAIN 两项设置与集群内使用的DNS相关,具体参考《在k8s中搭建可解析hostname的DNS服务》。每个pod启动时都要先启动一个/kubernetes/pause:latest容器来进行一些基本的初始化工作,该镜像默认下载地址为 gcr.io/google_containers/pause:latest,可通过POD_INFRA参数来更改下载地址。由于GWF的存在可能会连接不上该资源,所以可以将该镜像下载下来之后再push到自己的docker本地仓库中,启动 kubelet 时从本地仓库中读取即可。MAX_PODS参数表示一个节点最多可启动的pod数量。
启动Kubernetes Node 启动flanneld 1 2 3 systemctl daemon-reload systemctl start flanneld systemctl status -l flanneld
启动Docker 1 2 3 systemctl daemon-reload systemctl start docker systemctl status -l docker
查看Docker是否被Flannel托管 1 2 3 4 5 6 7 8 9 10 ps aux | grep docker /usr/bin/docke daemon -g /opt/domeos/openxxs/k8s-1.1.3-flannel/docker --bip=172.16.17.129/25 --ip-masq=true --mtu=1450 --insecure-registry 10.11.150.76:5000 ip link delete docker0 ip link delete flannel.1
启动kube-proxy 1 2 3 systemctl daemon-reload systemctl start kube-proxy systemctl status -l kube-proxy
启动kubelet 1 2 3 systemctl daemon-reload systemctl start kubelet systemctl status -l kubelet
测试Kubernetes 查看主机状态 1 2 3 4 5 6 ./kubectl --server=10.11.151.97:8080 get nodes NAME LABELS STATUS AGE tc-151-100 kubernetes.io/hostname=tc-151-100 Ready 9m tc-151-101 kubernetes.io/hostname=tc-151-101 Ready 17h
创建pod 创建test.yaml文件,内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 apiVersion: v1 kind: ReplicationController metadata: name: test-1 spec: replicas: 1 template: metadata: labels: app: test-1 spec: containers: - name: iperf image: 10.11.150.76:5000/openxxs/iperf:1.2 nodeSelector: kubernetes.io/hostname: tc-151-100 --- apiVersion: v1 kind: ReplicationController metadata: name: test-2 spec: replicas: 1 template: metadata: labels: app: test-2 spec: containers: - name: iperf image: 10.11.150.76:5000/openxxs/iperf:1.2 nodeSelector: kubernetes.io/hostname: tc-151-100 --- apiVersion: v1 kind: ReplicationController metadata: name: test-3 spec: replicas: 1 template: metadata: labels: app: test-3 spec: containers: - name: iperf image: 10.11.150.76:5000/openxxs/iperf:1.2 nodeSelector: kubernetes.io/hostname: tc-151-101 --- apiVersion: v1 kind: ReplicationController metadata: name: test-4 spec: replicas: 1 template: metadata: labels: app: test-4 spec: containers: - name: iperf image: 10.11.150.76:5000/openxxs/iperf:1.2 nodeSelector: kubernetes.io/hostname: tc-151-101
通过kubectl和test.yaml创建pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ./kubectl --server=10.11.151.97:8080 create -f test.yaml replicationcontroller "test-1" created replicationcontroller "test-2" created replicationcontroller "test-3" created replicationcontroller "test-4" created ./kubectl --server=10.11.151.97:8080 get pods NAME READY STATUS RESTARTS AGE test-1-vrt0s 1/1 Running 0 8m test-2-uwtj7 1/1 Running 0 8m test-3-59562 1/1 Running 0 8m test-4-m2rqw 1/1 Running 0 8m
获取四个pod对应container的IP地址
1 2 3 4 5 6 ./kubectl --server=10.11.151.97:8080 describe pod test-1-vrt0s IP 172.16.42.4