02月21, 2017

kubernetes 1.6.0 高可靠集群部署

这段时间要基于 kubernetes 来构建我们的容器化平台,所以陆续会有一波关于 kubernetes 及容器化的文章,敬请大家关注。

今天是第一篇,来说一下我们 kubernetes 集群的部署。

当前关于 kubernetes 的部署文章(包括官方文档)基本都是单 master 部署方式,满足不了高可靠的需求。我们基于多 master 节点的方式来实现 kubernetes 控制节点的高可靠。先看一张官方高可用的逻辑部署图

alt

根据这张图,我们来部署我们的 kubernetes 环境。

基础环境

  • 操作系统:CentOS 7.2
  • kubernetes: 1.6.0
  • etcd: 3.1.0
  • docker: 1.13.1
角色 主机 IP 组件
master01 kube.controller01 172.16.10.2 etcd、kube-apiserver、kube-scheduler、kube-controller-manager
master02 kube.controller02 172.16.10.3 etcd、kube-apiserver、kube-scheduler、kube-controller-manager
master03 kube.controller03 172.16.10.4 etcd、kube-apiserver、kube-scheduler、kube-controller-manager
node01 kube.node01 172.16.10.4 kubelet、kube-proxy、docker
node02 kube.node02 172.16.10.4 kubelet、kube-proxy、docker
node03 kube.node03 172.16.10.4 kubelet、kube-proxy、docker

基础组件安装

YUM 源更新

这里我们都是基于官方 release 自己打的 rpm 包放到自己的yum仓库中。

安装 ETCD

安装

因为是自己打的rpm包,所以安装非常简单

yum -y install addops-etcd-3.1.0-1.el7.x86_64

配置

路径 /etc/etcd/etcd.conf

修改 /usr/lib/systemd/system/etcd.service 中的 EnvironmentFile 如下: EnvironmentFile=-/etc/etcd/etcd.conf

官方配置默认在 /usr/lib/systemd/system/etcd.service 启动文件中设置, 由于 systemd 本身特性,每次在修改参数后都需要 systemctl daemon-reload 才能执行服务重启,这样很麻烦,所以我们将其配置单独拎出来放到了 /etc/etcd/etcd.conf 中,然后在启动文件中通过 EnvironmentFile=-/etc/etcd/etcd.conf 告诉 etcd 服务从这个配置文件读取变量。后面 kubernetes 组件同理。

# [member]
ETCD_NAME=kube.controller01
ETCD_DATA_DIR="/var/lib/etcd/kube.controller01.etcd"
ETCD_LISTEN_PEER_URLS="http://kube.controller01:2380"
ETCD_LISTEN_CLIENT_URLS="https://kube.controller01:2379,http://127.0.0.1:2379"
#
#
#[cluster]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://kube.controller01:2380"
ETCD_INITIAL_CLUSTER="app02=http://kube.controller01:2380,app03=http://kube.controller02:2380,app04=http://kube.controller03:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="YmpkdC10ZXN0"
ETCD_ADVERTISE_CLIENT_URLS="https://kube.controller01:2379"
#
#
#[proxy]
#ETCD_PROXY="off"
#
#[security]
ETCD_CERT_FILE="/etc/etcd/ssl/kube.controller01.crt"
ETCD_KEY_FILE="/etc/etcd/ssl/kube.controller01.key"
ETCD_CLIENT_CERT_AUTH="true"
ETCD_TRUSTED_CA_FILE="/etc/etcd/ssl/ca.crt"
#
#[logging]
ETCD_DEBUG="true"
ETCD_LOG_PACKAGE_LEVELS="etcdserver=WARNING,security=DEBUG"

以上配置项是我们经过裁剪后的,有一些参数有默认值我们没有修改,也就没有加到这里。其它支持的参数查看(etcd -h),可以根据自己的实际情况进行修改。

启动服务

3 个节点注册并启动服务

systemctl enable etcd.service

systemctl start etcd.service

验证

部署完成后,我们需要检验一下部署的是否成功,这里我们可以使用 etcdctl 这个命令行工具来对 etcd 进行验证:

etcdctl --ca-file=/root/.ssl/ca.crt --cert-file=/root/.ssl/etcd-client.crt --key-file=/root/.ssl/etcd-client.key cluster-health
member 497350af3952bc25  is healthy: got healthy result from https://kube.controller01:2379
member 50403524dd0d2c3d is healthy: got healthy result from https://kube.controller02:2379
member 8e8b64149fae0cdd  is healthy: got healthy result from https://kube.controller03:2379
cluster is healthy

我们看到 “cluster is healthy”,集群状态正常。

这里我们对 client 对 etcd 的访问打开了 tls 认证,client 访问时需要使用 https 访问,增加安全性(关于 tls 的配置,我会单独一篇来介绍)。

安装 kubernetes master 节点

安装

yum install -y addops-kubernetes-master-1.6.0-1.el7
yum install -y addops-kubernetes-1.6.0-1.el7
yum install -y addops-kubernetes-client-1.6.0-1.el7

配置

配置文件路径 /etc/kubernetes/master-config

这个配置文件也是我们自己添加的,原因同上,这里不再细说。不过要注意的是这里要修改3个启动文件

/usr/lib/systemd/system/kube-apiserver.service
/usr/lib/systemd/system/kube-scheduler.service
/usr/lib/systemd/system/kube-controller-manager.service
###
# kubernetes common config
KUBE_COMMON_ARGS="--logtostderr=false \
                  --v=3"

###
# kubernetes apiserver config
KUBE_API_ARGS="--etcd-servers=https://kube.controller01:2379,https://kube.controller02:2379,https://kube.controller03:2379 \
               --etcd-cafile=/etc/kubernetes/ssl/ca.crt \
               --etcd-certfile='/etc/kubernetes/ssl/etcd-client.crt' \
               --etcd-keyfile='/etc/kubernetes/ssl/etcd-client.key' \
               --authorization-mode=ABAC \
               --authorization-policy-file=/etc/kubernetes/policy.jsonl \
               --client-ca-file=/etc/kubernetes/ssl/ca.crt \
               --tls-cert-file='/etc/kubernetes/ssl/*.kube.apiserver.crt' \
               --tls-private-key-file='/etc/kubernetes/ssl/*.kube.apiserver.key' \
               --service-cluster-ip-range=192.168.0.0/16 \
               --allow-privileged=true"



###
# kubernetes scheduler config
KUBE_SCHEDULER_ARGS="--master=http://127.0.0.1:8080 \
                     --leader-elect=true \
                     --leader-elect-lease-duration=150s \
                     --leader-elect-renew-deadline=100s \
                     --leader-elect-retry-period=20s"
###
# kubernetes scheduler config
KUBE_CONTROLLER_MANAGER_ARGS="--master=http://127.0.0.1:8080 \
                              --leader-elect=true \
                              --leader-elect-lease-duration=150s \
                              --leader-elect-renew-deadline=100s \
                              --leader-elect-retry-period=20s"

启动服务

3 个节点注册并启动服务

systemctl enable kube-apiserver.service
systemctl enable kube-scheduler.service
systemctl enable kube-controller-manager.service

systemctl start kube-apiserver.service
systemctl start kube-scheduler.service
systemctl start kube-controller-manager.service

验证

可以通过 kubectl 命令工具来查看当前集群各个组件的运行状态

kubectl get componentstatuses

NAME                 STATUS      MESSAGE                                                                                ERROR
scheduler            Healthy     ok                                                                                     
controller-manager   Healthy     ok                                                                                     
etcd-0               Unhealthy   Get https://kube.controller01:2379/health: remote error: tls: bad certificate   
etcd-2               Unhealthy   Get https://kube.controller02:2379/health: remote error: tls: bad certificate   
etcd-1               Unhealthy   Get https://kube.controller03:2379/health: remote error: tls: bad certificate

从这里我们可以很明显看到 etcd 集群处于 Unhealthy 状态。

apiserver 是无状态的,所以对于多个节点而言可以通过前端挡一层 nginx 、haproxy 等实现高可用和负载均衡,而对于 scheduler 和 controller-managere 而言,它们需要操作后端存储 etcd,是有状态的,为了减少同步操作后端存储带来的数据不一致性,3 个 节点 的scheduler 和 controller-manager 组件同时只有一个提供服务,具体的实现就是3个节点之间会进行一个 leader 的选举,只有 leader 节点才提供服务。因此,验证选举工作是否正常也是非常重要的。

查看当前 3 个 shcduler和controller-manager 哪个是 leader 节点:

kubectl get endpoints kube-controller-manager --namespace=kube-system  -o yaml

知道当前哪个节点是 leader 后可以将其服务关闭,然后再查看 leader 节点是否发生变化,集群工作是否工作正常就OK了。

安装 kubrnetes node 节点

docker 安装

底层 driver 我们使用的是 devicemapper,后端存储的划分详见这里

划分好 docker 的后端存储后,就可以安装 docker engine 了

yum install -y docker-engine-selinux-1.12.1-1.el7.centos
yum install -y docker-engine-1.12.1-1.el7.centos

配置

配置我们也是把它单独拎出来,放到了 /etc/docker/daemon.json 中

{
        "authorization-plugins": [],
        "dns": [],
        "dns-opts": [],
        "dns-search": [],
        "exec-opts": ["native.cgroupdriver=cgroupfs"],
        "exec-root": "",
        "storage-driver": "devicemapper",
        "storage-opts": [
            "dm.thinpooldev=/dev/mapper/VolGroup00-thinpool",
            "dm.use_deferred_removal=true",
            "dm.use_deferred_deletion=true",
            "dm.blkdiscard=false",
            "dm.override_udev_sync_check=true"
        ],
        "labels": ["com.example.environment=\"production\""],
        "bip": "172.16.65.1/24",
        "ip-masq": true,
        "mtu": 1450,
        "iptables": true,
        "pidfile": "",
        "graph": "/data/docker",
        "cluster-store": "",
        "cluster-store-opts": {},
        "cluster-advertise": "",
        "max-concurrent-downloads": 3,
        "max-concurrent-uploads": 5,
        "debug": true,
        "hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"],
        "log-level": "",
        "api-cors-header": "",
        "selinux-enabled": false,
        "userns-remap": "",
        "group": "",
        "cgroup-parent": "",
        "raw-logs": false,
        "registry-mirrors": ["http://4093ad04.m.daocloud.io"],
        "disable-legacy-registry": true,
        "live-restore": true,
        "default-runtime": "runc"
}

配置中有几项需要配合 flannel 使用:

        "bip": "172.16.65.1/24",
        "ip-masq": true,
        "mtu": 1450,
        "iptables": true,

这个我们会在 flannel 的部署章节介绍。

kubelet 安装

yum install -y addops-kubernetes-1.6.0-1.el7
yum install -y addops-kubernetes-node-1.6.0-1.el7

配置

###
# kubernetes common config
KUBE_COMMON_ARGS="--logtostderr=false \
                  --v=2"

###
# kubernetes kubelet config
KUBELET_ARGS="--hostname-override=kube.node01 \
              --api-servers=https://kube.apiserver:6443 \
              --register-node=true \
              --kubeconfig=/etc/kubernetes/kubeconfig \
              --kube-reserved=cpu=500m,memory=512Mi \
              --pod-infra-container-image='r.addops.cn/public/pause-amd64:3.0'"

###
# kubernetes proxy config
KUBE_PROXY_ARGS="--hostname-override=kube.node01 \
                 --master=https://kube-apiserver:6443 \
                 --kubeconfig=/etc/kubernetes/kubeconfig \
                 --proxy-mode=iptables"

验证

在控制节点查看 node 的状态是否正常

kubectl get nodes

NAME             STATUS    AGE       VERSION
kube.node01      Ready     5d        v1.6.0
kube.node02      Ready     5d        v1.6.0
kube.node03      Ready     5d        v1.6.0

到此 kubernetes 的部署基本就结束了,剩下的就是功能性的验证了。

对于 TLS 和 Flannel 我们会单独写两篇文章单独介绍,感兴趣的可以注意查看,我们后续会发出。

补充 rpm 包的制作:

rpm 包的制作是我的同事 王浩宇 制作的,经过本人同意,现将其制作过程补充到这。

其实kubernetes的github已经给出了二进制文件,所以这里的打包重点就是如何通过spec文件来编排安装的问题。

rpm的制作主要是3个步骤: 3.1 从官方Release下载使用的src包。 包的组织结构如下:

   [root@k9309v /home/huomingming/kubernetes]# ll kubernetes
    total 4692
    drwxr-x---.  2 root root      19 Mar  3 07:21 client
    drwxr-x---. 22 root root    4096 Mar  3 07:21 cluster
    drwxr-x---. 12 root root    4096 Mar  3 07:21 docs
    drwxr-x---. 32 root root    4096 Mar  3 07:21 examples
    drwxr-x---.  5 root root      49 Mar  3 07:21 federation
    -rw-r-----.  1 root root 4766946 Mar  3 07:21 LICENSES
    -rw-r-----.  1 root root    5492 Mar  3 07:21 README.md
    drwxr-x---.  2 root root      82 Mar  3 07:21 server
    drwxr-x---.  3 root root      21 Mar  3 07:21 third_party
    -rw-r-----.  1 root root   11898 Mar  3 07:21 Vagrantfile
    -rw-r-----.  1 root root      14 Mar  3 07:21 version

3.2 根据其src包和k8s打包的流程书写spec文件(kubernetes-1.6.0.spec)。 我们的spec文件如下:

%define  debug_package  %{nil}
%define  _unpackaged_files_terminate_build 0

%define  name_prefix      addops
%define  software         kubernetes
%define  conf_dir         /etc/%{software}


Name:           %{name_prefix}-%{software}
Version:        1.6.0
Release:        2.el7
Summary:        Kubernetes

Group:          Applications/System
License:        ASL 2.0
Source0:        %{software}-%{version}.tar.gz
Source1:        %{software}-extra-%{version}.tar.gz
Packager:       Haoyu Wang <wanghaoyu@360.cn>
Autoreq:        0
Autoprov:       0

%description
Kubernetes

%package master
Summary: Kubernetes services for master host
Requires:       addops-kubernetes = %{version}-%{release}
Autoreq:        0
Autoprov:       0

%description master
Kubernetes services for master host

%package node
Summary: Kubernetes services for node host
Requires:       addops-kubernetes = %{version}-%{release}
Autoreq:        0
Autoprov:       0

%description node
Kubernetes services for node host

%package client
Summary: Kubernetes client tools
Autoreq:        0
Autoprov:       0

%description client
Kubernetes client tools like kubectl


%prep
%setup -q -n %{software}-%{version}
%setup -T -D -a 1 -n %{software}-%{version}


%build


%install
rm -rf %{buildroot}

# install binaries
binaries=(cloud-controller-manager hyperkube kubeadm kube-aggregator kube-apiserver kube-controller-manager kubectl kube-discovery kubefed kubelet kube-proxy kube-scheduler)
install -m 755 -d %{buildroot}%{_bindir}
for bin in "${binaries[@]}"; do
  echo "+++ INSTALLING ${bin}"
  install -p -m 755 -t %{buildroot}%{_bindir} server/bin/${bin}
done

#install conf files
install -d -m 0755 %{buildroot}%{conf_dir}
cp -r %{software}-extra-%{version}/etc/kubernetes/* %{buildroot}%{conf_dir}
cp %{software}-extra-%{version}/etc/dockercfg %{buildroot}/.dockercfg

# install service files
install -d -m 0755 %{buildroot}%{_unitdir}
install -m 0644 -t %{buildroot}%{_unitdir} %{software}-extra-%{version}/init/systemd/*.service

# install the place the kubelet defaults to put volumes
install -d %{buildroot}%{_sharedstatedir}/kubelet

install -d -m 0755 %{buildroot}%{_tmpfilesdir}
install -p -m 0644 -t %{buildroot}/%{_tmpfilesdir} %{software}-extra-%{version}/init/systemd/tmpfiles.d/kubernetes.conf

# install the bash completion
#install -d -m 0755 %{buildroot}%{_datadir}/bash-completion/completions/
#install -t %{buildroot}%{_datadir}/bash-completion/completions/ contrib/completions/bash/kubectl


%post master
%systemd_post kube-apiserver kube-scheduler kube-controller-manager


%preun master
%systemd_preun kube-apiserver kube-scheduler kube-controller-manager


%postun master
%systemd_postun


%post node
%systemd_post kubelet kube-proxy


%preun node
%systemd_preun kubelet kube-proxy


%postun node
%systemd_postun


%clean
#rm -rf %{buildroot}


%files
%dir %{conf_dir}
%dir %{conf_dir}/ssl
%{conf_dir}/ssl/ca.crt
%{_tmpfilesdir}/kubernetes.conf

%files master
%{_bindir}/cloud-controller-manager
%{_bindir}/hyperkube
%{_bindir}/kubeadm
%{_bindir}/kube-aggregator
%{_bindir}/kube-apiserver
%{_bindir}/kube-controller-manager
%{_bindir}/kube-discovery
%{_bindir}/kube-scheduler
%{_unitdir}/kube-apiserver.service
%{_unitdir}/kube-controller-manager.service
%{_unitdir}/kube-scheduler.service
%config(noreplace) %{conf_dir}/master-config
%config(noreplace) %{conf_dir}/policy.jsonl
%{conf_dir}/ssl/*.k8s.360.cn.crt
%{conf_dir}/ssl/*.k8s.360.cn.key

%files node
%{_bindir}/kubelet
%{_bindir}/kube-proxy
%{_unitdir}/kube-proxy.service
%{_unitdir}/kubelet.service
%dir %{_sharedstatedir}/kubelet
%config(noreplace) %{conf_dir}/node-config
%config(noreplace) %{conf_dir}/kubeconfig
%{conf_dir}/ssl/kube-node.crt
%{conf_dir}/ssl/kube-node.key
/.dockercfg

%files client
%{_bindir}/kubectl
%{_bindir}/kubefed
#%{_datadir}/bash-completion/completions/kubectl


%changelog
- First Build

3.3 通过第二步中的spec文件打包 rpmbuild -bb kubernetes-1.6.0.spec 生成rpm包。

整个过程就是这样。

本文链接:https://www.opsdev.cn/post/kubernetes-deployment.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。