【K8s】二进制部署Kubernetes v1.8.15集群环境管理Docker容器
Kubernetes介绍
Kubernetes是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernetes也叫K8S。
K8S是Google内部一个叫Borg的容器集群管理系统衍生出来的,Borg已经在Google大规模生产运行十年之久。
K8S主要用于自动化部署、扩展和管理容器应用,提供了资源调度、部署管理、服务发现、扩容缩容、监控等一整套功能。
2015年7月,Kubernetes v1.0正式发布,截止到2017年9月29日最新稳定版本是v1.8。
Kubernetes目标是让部署容器化应用简单高效。
官方网站:www.kubernetes.io
Kubernetes主要功能:
n数据卷 Pod中容器之间共享数据,可以使用数据卷。
n应用程序健康检查 容器内服务可能进程堵塞无法处理请求,可以设置监控检查策略保证应用健壮性。
n复制应用程序实例 控制器维护着Pod副本数量,保证一个Pod或一组同类的Pod数量始终可用。
n弹性伸缩 根据设定的指标(CPU利用率)自动缩放Pod副本数。
n服务发现 使用环境变量或DNS服务插件保证容器中程序发现Pod入口访问地址。
n负载均衡 一组Pod副本分配一个私有的集群IP地址,负载均衡转发请求到后端容器。在集群内部其他Pod可通过这个ClusterIP访问应用。
n滚动更新 更新服务不中断,一次更新一个Pod,而不是同时删除整个服务。
n服务编排 通过文件描述部署服务,使得应用程序部署变得更高效。
n资源监控 Node节点组件集成cAdvisor资源收集工具,可通过Heapster汇总整个集群节点资源数据,然后存储到InfluxDB时序数据库,再由Grafana展示。
n提供认证和授权 支持属性访问控制(ABAC)、角色访问控制(RBAC)认证授权策略。
基本对象概念
基本对象:
nPod Pod是最小部署单元,一个Pod有一个或多个容器组成,Pod中容器共享存储和网络,在同一台Docker主机上运行。
nService Service一个应用服务抽象,定义了Pod逻辑集合和访问这个Pod集合的策略。
Service代理Pod集合对外表现是为一个访问入口,分配一个集群IP地址,来自这个IP的请求将负载均衡转发后端Pod中的容器。Service通过LableSelector选择一组Pod提供服务。
nVolume
数据卷,共享Pod中容器使用的数据。
nNamespace
命名空间将对象逻辑上分配到不同Namespace,可以是不同的项目、用户等区分管理,并设定控制策略,从而实现多租户。
命名空间也称为虚拟集群。
nLable
标签用于区分对象(比如Pod、Service),键/值对存在;每个对象可以有多个标签,通过标签关联对象。
基于基本对象更高层次抽象:
nReplicaSet
下一代ReplicationController。确保任何给定时间指定的Pod副本数量,并提供声明式更新等功能。
RC与RS唯一区别就是lableselector支持不同,RS支持新的基于集合的标签,RC仅支持基于等式的标签。
nDeployment
Deployment是一个更高层次的API对象,它管理ReplicaSets和Pod,并提供声明式更新等功能。
官方建议使用Deployment管理ReplicaSets,而不是直接使用ReplicaSets,这就意味着可能永远不需要直接操作ReplicaSet对象。
nStatefulSet
StatefulSet适合持久性的应用程序,有唯一的网络标识符(IP),持久存储,有序的部署、扩展、删除和滚动更新。
nDaemonSet
DaemonSet确保所有(或一些)节点运行同一个Pod。当节点加入Kubernetes集群中,Pod会被调度到该节点上运行,当节点从集群中移除时,DaemonSet的Pod会被删除。删除DaemonSet会清理它所有创建的Pod。
nJob
一次性任务,运行完成后Pod销毁,不再重新启动新容器。还可以任务定时运行。
系统架构及组件功能
Master组件:
nkube-apiserver
Kubernetes API,集群的统一入口,各组件协调者,以HTTPAPI提供接口服务,所有对象资源的增删改查和监听操作都交给APIServer处理后再提交给Etcd存储。
nkube-controller-manager
处理集群中常规后台任务,一个资源对应一个控制器,而ControllerManager就是负责管理这些控制器的。
nkube-scheduler
根据调度算法为新创建的Pod选择一个Node节点。
Node组件:
nkubelet
kubelet是Master在Node节点上的Agent,管理本机运行容器的生命周期,比如创建容器、Pod挂载数据卷、下载secret、获取容器和节点状态等工作。kubelet将每个Pod转换成一组容器。
nkube-proxy
在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作。
ndocker或rocket(rkt)
运行容器。
第三方服务:
netcd
分布式键值存储系统。用于保持集群状态,比如Pod、Service等对象信息。
K8S集群部署有几种方式:kubeadm、minikube和二进制包。前两者属于自动部署,简化部署操作,这里强烈推荐初学者使用二进制包部署,因为自动部署屏蔽了很多细节,使得对各个模块感知很少,非常不利学习。
使用二进制包快速部署一套Kubernetes集群。
本章目录
一、架构拓扑图
二、环境规划
三、部署集群
3.1 下载二进制包
3.2 安装etcd3
3.3 运行Master节点组件
3.3.1 apiserver
3.3.2 shceduler
3.3.3 controller-manager
3.3.4 小结
3.4 运行Node节点组件
3.4.1 kubelet
3.4.2 proxy
3.3.3 小结
3.5 验证集群是否部署成功
一、架构拓扑图
环境规划
角色 |
IP |
组件 |
Node01 |
192.168.3.71 |
etcd,kube-apiserver,kube-controller-manager,kube-scheduler,flannel,docker |
node02 |
192.168.3.72 |
kubelet、kube-proxy、docker、flannel |
node03 |
192.168.3.73 |
kubelet、kube-proxy、docker、flannel |
环境说明:
操作系统:RHEL 7.5
Kubernetes版本:v1.8.15
Docker版本:v17.09-ce
均采用当前最新稳定版本。
关闭selinux。
【Master、Node1、Node2】
1、关闭SElinux和防火墙
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
sestatus
systemctl disable firewalld.service && systemctl stop firewalld.service
firewall-cmd --state
2、修改各个节点的主机名
【Master、Node1、Node2】
hostnamectl set-hostname node1
hostnamectl set-hostname node2
hostnamectl set-hostname node3
3、修改hosts文件,使用本地解析主机名
【Master、Node1、Node2】
cat > /etc/hosts <<EOF
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.3.71 node1
192.168.3.72 node2
192.168.3.73 node3
EOF
4、master节点与node节点做互信
【Master】
[root@master ~]# ssh-keygen -t rsa -P ''
ssh-copy-id node1
ssh-copy-id node2
ssh-copy-id node3
5、关闭Swap
【Master、Node1、Node2】
swapoff -a
sed -i "11s/UUID/#&/" /etc/fstab
free -m
6、配置系统路由参数,防止kubeadm报路由警告,开启ipv4转发
【Master、Node1、Node2】
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
sysctl -a | grep "net.ipv4.ip_forward"
7、修改文件最大打开数量(可不设置)
【Master、Node1、Node2】
cat <<EOF > /etc/security/limits.d/20-nproc.conf
* soft nproc 20480
* hard nproc 20480
* soft nofile 102400
* hard nofile 102400
root soft nproc unlimited
EOF
8、加载内核模块并检查nf_conntrack_ipv4及ip_forward模块是否加载
【Node1、Node2】
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
lsmod | grep -e ipvs -e nf_conntrack_ipv4
9、配置时钟服务器端并启动chronyd
【Master】
[root@k8s-m ~]#
sed -i "3s/0.rhel.pool.ntp.org/ntp1.aliyun.com/" /etc/chrony.conf
sed -i "4s/1.rhel.pool.ntp.org/ntp2.aliyun.com/" /etc/chrony.conf
sed -i "5s/2.rhel.pool.ntp.org/ntp3.aliyun.com/" /etc/chrony.conf
sed -i "6s/3.rhel.pool.ntp.org/ntp4.aliyun.com/" /etc/chrony.conf
sed -i -e "26s@allow 192.168.0.0/16@allow 192.168.3.0/24@" /etc/chrony.conf
systemctl enable chronyd.service && systemctl start chronyd.service && systemctl status chronyd.service
【Node1、Node2】
配置Node2、Node3时钟服务客户端并启动服务
[root@k8s-n ~]#
sed -i "3s/0.rhel.pool.ntp.org/node1.example.cn/" /etc/chrony.conf
sed -i "4s/server 1.rhel.pool.ntp.org/#server 1.rhel.pool.ntp.org/" /etc/chrony.conf
sed -i "5s/server 2.rhel.pool.ntp.org/#server 2.rhel.pool.ntp.org/" /etc/chrony.conf
sed -i "6s/server 3.rhel.pool.ntp.org/#server 3.rhel.pool.ntp.org/" /etc/chrony.conf
systemctl enable chronyd.service && systemctl start chronyd.service && systemctl status chronyd.service
10、安装docker-ce
【Master、Node1、Node2】
1)下载docker-ce仓库
yum -y install yum-utils device-mapper-persistent-data lvm2 conntrack-tools bridge-utils ipvsadm
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum makecache fast
#查看安装版本
yum list docker-ce --showduplicates |sort -r
yum list docker-ce-selinux --showduplicates |sort -r
2)安装docker-ce
yum -y install --setopt=obsoletes=0 docker-ce-17.03.3.ce-1.el7 docker-ce-selinux-17.03.3.ce-1.el7
systemctl enable docker && systemctl start docker && systemctl status docker
11、添加Docker加速器
【Master、Node1、Node2】
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://u6g7us5g.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload && systemctl restart docker && systemctl status docker
四、部署集群
3.1 下载二进制包
下载下面两个红色框包。
https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.8.md#v1815
3.2.2 二进制安装eted
下载安装
wget https://github.com/etcd-io/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz
复制命令到/usr/bin目录
tar -zxvf etcd-v3.3.10-linux-amd64.tar.gz && rm -rf etcd-v3.3.10-linux-amd64.tar.gz
cp -v etcd-v3.3.10-linux-amd64/{etcd,etcdctl} /usr/bin
rm -rf etcd-v3.3.10-linux-amd64
配置
创建etcd所需的数据目录/var/lib/etcd
mkdir -p /var/lib/etcd /etc/etcd
创建配置文件,注意这里IP配置必须是内网IP,公网IP会启动不
cat > /etc/etcd/etcd.conf <<EOF
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://0.0.0.0:2379"
EOF
创建启动服务
cat > /usr/lib/systemd/system/etcd.service <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
WorkingDirectory=/var/lib/etcd
EnvironmentFile=-/etc/etcd/etcd.conf
ExecStart=/usr/bin/etcd
Restart=on-failure
# Restart=always
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
启动etcd服务
systemctl daemon-reload && systemctl enable etcd && systemctl restart etcd && systemctl status etcd
ss -antulp | grep etcd
④检验etcd是否安装成功
[root@k8s-m ~]# etcdctl cluster-health
member 8e9e05c52164694d is healthy: got healthy result from http://10.0.0.211:2379
cluster is healthy
3、部署k8s-Master节点组件
3.3 Master节点部署组件
下载并解压kubernetes-server-linux-amd64.tar.gz
https://storage.googleapis.com/kubernetes-release/release/v1.11.4/kubernetes-server-linux-amd64.tar.gz
[root@k8s-m ~]#
wget --no-check-certificate https://dl.k8s.io/v1.8.15/kubernetes-server-linux-amd64.tar.gz
tar -zxvf kubernetes-server-linux-amd64.tar.gz && rm -rf kubernetes-server-linux-amd64.tar.gz
将二进制命令kube-apiserver、kube-controller-manager、kube-scheduler、kubectl、kubeadm复制到/usr/bin下
[root@k8s-m ~]#
cp -v kubernetes/server/bin/{kube-apiserver,kube-scheduler,kube-controller-manager,kubectl} /usr/bin
创建配置目录
[root@k8s-m ~]# mkdir -p /etc/kubernetes
①配置kube-apiserver.service服务
[root@k8s-m ~]# cat > /etc/kubernetes/kube-apiserver <<EOF
# 启用日志标准错误
KUBE_LOGTOSTDERR="--logtostderr=true"
# 日志级别
KUBE_LOG_LEVEL="--v=4"
# Etcd服务地址
KUBE_ETCD_SERVERS="--etcd-servers=http://192.168.3.71:2379"
# API服务监听地址
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
# API服务监听端口
KUBE_API_PORT="--insecure-port=8080"
# 对集群中成员提供API服务地址
KUBE_ADVERTISE_ADDR="--advertise-address=192.168.3.71"
# 允许容器请求特权模式,默认false
KUBE_ALLOW_PRIV="--allow-privileged=false"
# 集群分配的IP范围
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=192.168.3.0/24"
EOF
启动服务systemd:
[root@k8s-m ~]# vim /usr/lib/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/etc/kubernetes/kube-apiserver
#ExecStart=/usr/bin/kube-apiserver ${KUBE_APISERVER_OPTS}
ExecStart=/usr/bin/kube-apiserver \
${KUBE_LOGTOSTDERR} \
${KUBE_LOG_LEVEL} \
${KUBE_ETCD_SERVERS} \
${KUBE_API_ADDRESS} \
${KUBE_API_PORT} \
${KUBE_ADVERTISE_ADDR} \
${KUBE_ALLOW_PRIV} \
${KUBE_SERVICE_ADDRESSES}
Restart=on-failure
[Install]
WantedBy=multi-user.target
启动服务,并设置开机自启
[root@k8s-m ~]# systemctl daemon-reload && systemctl enable kube-apiserver && systemctl restart kube-apiserver && systemctl status kube-apiserver
②配置kube-scheduler服务
配置文件:
cat > /etc/kubernetes/kube-scheduler <<EOF
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=4"
KUBE_MASTER="--master=192.168.3.71:8080"
KUBE_LEADER_ELECT="--leader-elect"
EOF
systemd服务文件:
vim /usr/lib/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/etc/kubernetes/kube-scheduler
ExecStart=/usr/bin/kube-scheduler \
${KUBE_LOGTOSTDERR} \
${KUBE_LOG_LEVEL} \
${KUBE_MASTER} \
${KUBE_LEADER_ELECT}
Restart=on-failure
[Install]
WantedBy=multi-user.target
启动服务并设置开机启动
systemctl daemon-reload && systemctl enable kube-scheduler && systemctl restart kube-scheduler && systemctl status kube-scheduler
③配置kube-controller-manger
配置文件:
cat > /etc/kubernetes/kube-controller-manager <<EOF
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=4"
KUBE_MASTER="--master=192.168.3.71:8080"
EOF
systemd服务文件
vim /usr/lib/systemd/system/kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/etc/kubernetes/kube-controller-manager
ExecStart=/usr/bin/kube-controller-manager \
${KUBE_LOGTOSTDERR} \
${KUBE_LOG_LEVEL} \
${KUBE_MASTER} \
${KUBE_LEADER_ELECT}
Restart=on-failure
[Install]
WantedBy=multi-user.target
启动服务并设置开机自启
systemctl daemon-reload && systemctl enable kube-controller-manager && systemctl restart kube-controller-manager && systemctl status kube-controller-manager
至此Master节点组件就全部启动了,需要注意的是服务启动顺序有依赖,先启动etcd,再启动apiserver,其他组件无顺序要求
查看Master节点组件运行进程
[root@k8s-master ~]# ps -ef|grep kube
验证Master节点功能
[root@k8s-master ~]# kubectl get componentstatuses
NAME STATUS MESSAGE ERROR
etcd-0 Healthy {"health": "true"}
controller-manager Healthy ok
scheduler Healthy ok
如果启动失败,查看日志
[root@k8s-master ~]# journalctl -u kube-apiserver
部署K8s-Node节点组件
#上传kubernetes-node-linux-amd64.tar.gz#
tar -zxvf kubernetes-node-linux-amd64.tar.gz && rm -rf kubernetes-node-linux-amd64.tar.gz
cp -v kubernetes/node/bin/{kubelet,kube-proxy} /usr/bin
mkdir /etc/kubernetes
①配置kubelet服务
创建kubeconfig配置文件:kubeconfig文件用于kubelet连接master apiserver
cat > /etc/kubernetes/kubelet.kubeconfig <<EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
server: http://192.168.3.71:8080
name: local
contexts:
- context:
cluster: local
name: local
current-context: local
EOF
创建kubelet配置文件
cat > /etc/kubernetes/kubelet <<EOF
# 启用日志标准错误
KUBE_LOGTOSTDERR="--logtostderr=true"
# 日志级别
KUBE_LOG_LEVEL="--v=4"
# Kubelet服务IP地址NODE_ADDRESS="--address=192.168.3.72"
# Kubelet服务端口
NODE_PORT="--port=10250"
# 自定义节点名称NODE_HOSTNAME="--hostname-override=192.168.3.72"
# kubeconfig路径,指定连接API服务器KUBELET_KUBECONFIG="--kubeconfig=/etc/kubernetes/kubelet.kubeconfig"
# 允许容器请求特权模式,默认false
KUBE_ALLOW_PRIV="--allow-privileged=false"
# DNS信息
KUBELET_DNS_IP="--cluster-dns=192.168.3.1"
KUBELET_DNS_DOMAIN="--cluster-domain=cluster.local"
# 禁用使用Swap
KUBELET_SWAP="--fail-swap-on=false"
EOF
systemd服务文件
vim /usr/lib/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service
[Service]
EnvironmentFile=-/etc/kubernetes/kubelet
ExecStart=/usr/bin/kubelet \
${KUBE_LOGTOSTDERR} \
${KUBE_LOG_LEVEL} \
${NODE_ADDRESS} \
${NODE_PORT} \
${NODE_HOSTNAME} \
${KUBELET_KUBECONFIG} \
${KUBE_ALLOW_PRIV} \
${KUBELET_DNS_IP} \
${KUBELET_DNS_DOMAIN} \
${KUBELET_SWAP}
Restart=on-failure
KillMode=process
[Install]
WantedBy=multi-user.target
启动服务并设置开机自启
systemctl daemon-reload && systemctl enable kubelet && systemctl restart kubelet && systemctl status kubelet
②配置kube-proxy服务
配置文件
cat > /etc/kubernetes/kube-proxy <<EOF
# 启用日志标准错误
KUBE_LOGTOSTDERR="--logtostderr=true"
# 日志级别
KUBE_LOG_LEVEL="--v=4"
# 自定义节点名称
NODE_HOSTNAME="--hostname-override=192.168.3.72"
# API服务地址
KUBE_MASTER="--master=http://192.168.3.72:8080"
EOF
systemd服务文件
vim /usr/lib/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
EnvironmentFile=-/etc/kubernetes/kube-proxy
ExecStart=/usr/bin/kube-proxy \
${KUBE_LOGTOSTDERR} \
${KUBE_LOG_LEVEL} \
${NODE_HOSTNAME} \
${KUBE_MASTER}
Restart=on-failure
[Install]
WantedBy=multi-user.target
启动服务并设置开机自启
systemctl daemon-reload && systemctl enable kube-proxy && systemctl restart kube-proxy && systemctl status kube-proxy
③部署Flannel网络
下载安装
wget https://github.com/coreos/flannel/releases/download/v0.9.1/flannel-v0.9.1-linux-amd64.tar.gz
tar -zxvf flannel-v0.9.1-linux-amd64.tar.gz && rm -rf flannel-v0.9.1-linux-amd64.tar.gz
cp flanneld mk-docker-opts.sh /usr/bin
systemd服务文件
vim /usr/lib/systemd/system/flanneld.service
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service
[Service]
Type=notifyEnvironmentFile=/etc/kubernetes
EnvironmentFile=-/etc/sysconfig/docker-network
ExecStart=/usr/bin/flanneld-start $FLANNEL_OPTIONS
ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure
[Install]
WantedBy=multi-user.target
WantedBy=docker.servic
配置文件:master、node都需要执行
cat /app/flannel/conf/flanneld
# Flanneld configuration options
# etcd url location. Point this to the server where etcd runsFLANNEL_ETCD_ENDPOINTS="http://10.0.0.211:2379"
# etcd config key. This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_KEY="/k8s/network"
# Any additional options that you want to pass
#FLANNEL_OPTIONS=""
FLANNEL_OPTIONS="--logtostderr=false --log_dir=/var/log/k8s/flannel/ --etcd-endpoints=http://10.0.0.211:2379"
启动服务并设置开机自启
Master执行:
etcdctl set /k8s/network/config '{ "Network": "172.16.0.0/16" }'
systemctl daemon-reload
systemctl enable flanneld.service
systemctl start flanneld.service
验证服务:
journalctl -u flanneld |grep 'Lease acquired'
9月 03 17:58:02 k8s-node-1 flanneld[9658]: I0903 17:58:02.862074 9658 manager.go:250] Lease acquired: 10.0.11.0/24
9月 03 18:49:47 k8s-node-1 flanneld[11731]: I0903 18:49:47.882891 11731 manager.go:250] Lease acquire: 10.0.11.0/24
④启动Flannel之后,需要依次重启docker、kubernete
Master节点执行:
systemctl restart docker.service
systemctl restart kube-apiserver.service
systemctl restart kube-controller-manager.service
systemctl restart kube-scheduler.service
Node节点执行:
systemctl restart docker.service
systemctl restart kubelet.service
systemctl restart kube-proxy.service
Master节点查看IP信息
Node节点查看IP信息
小结:查看docker0和flannel0的网络设备,确保每个Node上的Docker0和flannel0在同一段内,并且不同节点的网段都被划分在172.16.0.0/16 的不同段内。如Master是172.16.88.0/16,Node1是172.16.65.0/16