Kubernetes部署方案
Kubernetes部署方案
1 目标
K8S集群部署有几种方式:kubeadm、minikube和二进制包。前两者属于自动部署,简化部署操作。但自动部署屏蔽了很多细节,使得对各个模块感知很少,本文主要采用二进制包手动部署。
部署过程中所涉及到的设备、接口及管理网口的IP地址如下表所示:
设备名称 | IP地址 | 组件 |
---|---|---|
master | 192.168.4.154 | etcd kube-apiserver kube-controller-manager kube-scheduler |
node1 | 192.168.4.155 | etcd kubelet kube-proxy docker |
node2 | 192.168.4.156 | etcd kubelet kube-proxy docker |
表1:设备管理口IP及组件列表
2 硬件与软件环境
部署环境中涉及到的硬件和软件如表2和表3所示:
名称 | 型号 | 硬件指标 | 数量 | 备注 |
---|---|---|---|---|
服务器 | CPU:至少2核 内存:最低2 磁盘:不少于20G | 3 |
表2:硬件环境
软件 | 版本 | 备注 |
---|---|---|
操作系统 | Centos7.6 | 安装时选择Compute Node 模式 |
Kubernetes | 1.18.0 | |
Docker | Docker-ce19.03 | |
Etcd | 3.3.11 |
表3:软件环境
3 Kubernetes简介
Kubernetes 是是一个基于容器技术的分布式架构领先方案。Kubernetes(k8s)是Google开源的容器集群管理系统,Kubernetes简称K8S,K8S用于容器化应用程序的部署,扩展和管理。K8S提供了容器编排,资源调度,弹性伸缩,部署管理,服务发现等一系列功能。
- Kubernetes集群架构
- Kubernetes核心概念
cluster
cluster是 计算、存储和网络资源的集合,k8s利用这些资源运行各种基于容器的应用。
master
master是cluster的大脑,他的主要职责是调度,即决定将应用放在那里运行。master运行linux操作系统,可以是物理机或者虚拟机。为了实现高可用,可以运行多个master。
node
node的职责是运行容器应用。node由master管理,node负责监控并汇报容器的状态,同时根据master的要求管理容器的生命周期。node运行在linux的操作系统上,可以是物理机或者是虚拟机。
pod
pod是k8s的最小工作单元。每个pod包含一个或者多个容器。pod中的容器会作为一个整体被master调度到一个node上运行。
controller-manager
k8s通常不会直接创建pod,而是通过controller-manager来管理pod的。controller-manager中定义了pod的部署特性,比如有几个副本,在什么样的node上运行等。为了满足不同的业务场景,k8s提供了多种controller-manager,包括deployment、replicaset、daemonset、statefulset、job等。
1) deployment
是最常用的controller。deployment可以管理pod的多个副本,并确保pod按照期望的状态运行。
2) replicaset
实现了pod的多副本管理。使用deployment时会自动创建replicaset,也就是说deployment是通过replicaset来管理pod的多个副本的,我们通常不需要直接使用replicaset。
3) daemonset
用于每个node最多只运行一个pod副本的场景。正如其名称所示的,daemonset通常用于运行daemon。
4) statefuleset
能够保证pod的每个副本在整个生命周期中名称是不变的,而其他controller不提供这个功能。当某个pod发生故障需要删除并重新启动时,pod的名称会发生变化,同时statefulset会保证副本按照固定的顺序启动、更新或者删除。、
5) job
用于运行结束就删除的应用,而其他controller中的pod通常是长期持续运行的。
service
deployment可以部署多个副本,每个pod 都有自己的IP,外界通过service访问这些副本。
k8s的 service定义了外界访问一组特定pod的方式。service有自己的IP和端口,service为pod提供了负载均衡。
k8s运行容器pod与访问容器这两项任务分别由controller和service执行。
namespace
可以将一个物理的cluster逻辑上划分成多个虚拟cluster,每个cluster就是一个namespace。不同的namespace里的资源是完全隔离的。
lable
标签用于区分对象(比如pod、service),键/值对存在;每个对象可以有多个标签,通过标签关联对象。
- K8s的Master组件
kube-apiserver
Kubernetes API,集群的统一入口,各组件协调者,以RESTful API提供接口服务,所有对象资源的增删改查和监听操作都交给APIServer处理后再提交给Etcd存储。
kube-controller-manager
处理集群中常规后台任务,一个资源对应一个控制器 ,而ControllerManager就是负责管理这些控制器的
kube-scheduler
根据调度算法为新创建的Pod选择一个Node节点,可以任意部署,可以部署在同一个节点上,也可以部署在不同的节点上。
Etcd
分布式键值存储系统。用于保存集群状态数据,比如Pod、Service等对象信息。
- K8s的Node组件
Kubelet
kubelet是Master在Node节点上的Agent,管理本机运行容器的生命周期,比如创建容器、Pod挂载数据卷、下载secret. 获取容器和节点状态等工作。kubelet将每个Pod转换成一组容器。
kube-proxy
在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作。
docker或rocket
容器引擎,运行容器。
4 安装步骤
4.1 准备环境
注意:以下步骤各节点统一执行
- 关闭交换分区:
[root@localhost ~]#swapoff -a && sysctl -w vm.swappiness=0
- 注释掉开机启动交换分区:
[root@localhost ~]sed -i 's/.*swap.*/#&/g' /etc/fstab
- 关闭防火墙:
[root@localhost ~]systemctl stop firewalld
[root@localhost ~] systemctl disable firewalld
- 禁用Selinux:
[root@localhost ~]# setenforce 0
[root@localhost ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux
- 设置透明网桥:
[root@localhost ~]#cat > /etc/sysctl.d/k8s.conf << EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
modprobe br_netfilter
sysctl -p /etc/sysctl.d/k8s.conf
- 安装Docker:
[root@localhost ~]# yum -y install yum-utils
[root@localhost ~]# yum-config-manager --add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@localhost ~]#yum install docker-ce
[root@localhost ~]#curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://bc437cce.m.daocloud.io
[root@localhost ~]# systemctl enable docker
[root@localhost ~]#systemctl start docker
- 同步时间:
[root@localshot ~]# yum -y install ntp
[root@localhost ~]# vi /etc/ntp.conf
修改server ntp1.aliyun.com iburst
[root@localhost ~]# systemctl restart ntpd
[root@localhost ~]# timedatectl set-timezone Asia/Shanghai
[root@localhost ~]#cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
- 修改系统打开文件最大数量:
[root@localhost ~]# vi /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
4.2 部署Etcd集群
- 下载cfssl工具并生成证书:
下载cfssl工具
[root@k8s-master ~]#wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
[root@k8s-master ~]#wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
[root@k8s-master ~]#wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
[root@k8s-master ~]#chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
[root@k8s-master ~]#mv cfssl_linux-amd64 /usr/local/bin/cfssl
[root@k8s-master ~]#mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
[root@k8s-master ~]#mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
创建以下三个文件:
[root@k8s-master ~]#vim ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"www": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
[root@k8s-master ~]#vim ca-csr.json
{
"CN": "etcd CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing"
}
]
}
[root@k8s-master ~]#vim server-csr.json
{
"CN": "etcd",
"hosts": [
"192.168.4.154",
"192.168.4.155",
"192.168.4.156"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
生成证书
[root@k8s-master ~]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
[root@k8s-master ~]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
[root@k8s-master ~]# ls *pem
ca-key.pem ca.pem server-key.pem server.pem
- 安装Etcd3:
创建文件夹
[root@k8s-master ~]# mkdir /opt/etcd/{bin,cfg,ssl} -p
下载etcd相关包
[root@k8s-master ~]#wget https://github.com/etcd-io/etcd/releases/download/v3.2.12/etcd-v3.2.12-linux-amd64.tar.gz
[root@k8s-master ~]#tar zxvf etcd-v3.2.12-linux-amd64.tar.gz
[root@k8s-master ~]#mv etcd-v3.2.12-linux-amd64/{etcd,etcdctl} /opt/etcd/bin/
创建etcd配置⽂件
[root@k8s-master ~]#vim /opt/etcd/cfg/etcd
#[Member]
ETCD_NAME="etcd01"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.4.154:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.4.154:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.4.154:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.4.154:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.4.154:2380,etcd02=https://192.168.4.155:2380,etcd03=https://192.168.4.156:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
- ETCD_NAME 节点名称
- ETCD_DATA_DIR 数据⽬录
- ETCD_LISTEN_PEER_URLS 集群通信监听地址
- ETCD_LISTEN_CLIENT_URLS 客户端访问监听地址
- ETCD_INITIAL_ADVERTISE_PEER_URLS 集群通告地址
- ETCD_ADVERTISE_CLIENT_URLS 客户端通告地址
- ETCD_INITIAL_CLUSTER 集群节点地址
- ETCD_INITIAL_CLUSTER_TOKEN 集群Token
- ETCD_INITIAL_CLUSTER_STATE 加⼊集群的当前状态,new是新集群,existing表⽰加⼊已有集群
修改etcd开机启动
[root@k8s-master ~]# vim /usr/lib/systemd/system/etcd.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=/opt/etcd/cfg/etcd
ExecStart=/opt/etcd/bin/etcd \
--name=${ETCD_NAME} \
--data-dir=${ETCD_DATA_DIR} \
--listen-peer-urls=${ETCD_LISTEN_PEER_URLS} \
--listen-client-urls=${ETCD_LISTEN_CLIENT_URLS},http://127.0.0.1:2379 \
--advertise-client-urls=${ETCD_ADVERTISE_CLIENT_URLS} \
--initial-advertise-peer-urls=${ETCD_INITIAL_ADVERTISE_PEER_URLS} \
--initial-cluster=${ETCD_INITIAL_CLUSTER} \
--initial-cluster-token=${ETCD_INITIAL_CLUSTER_TOKEN} \
--initial-cluster-state=new \
--cert-file=/opt/etcd/ssl/server.pem \
--key-file=/opt/etcd/ssl/server-key.pem \
--peer-cert-file=/opt/etcd/ssl/server.pem \
--peer-key-file=/opt/etcd/ssl/server-key.pem \
--trusted-ca-file=/opt/etcd/ssl/ca.pem \
--peer-trusted-ca-file=/opt/etcd/ssl/ca.pem
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
把刚才生成的证书拷贝到配置文件中的位置:
[root@k8s-master ~]# cp ca*pem server*pem /opt/etcd/ssl
启动etcd并设置开机启动:
[root@k8s-master ~]# systemctl enable etcd
[root@k8s-master ~]# systemctl start etcd
注:三台机器的etcd要同时启动,否则会失败。
检查etcd集群状态:
[root@k8s-master ~]# /opt/etcd/bin/etcdctl \
--ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem \
--key-file=/opt/etcd/ssl/server-key.pem \
--endpoints="https://192.168.4.154:2379,https://192.168.4.155:2379,https://192.168.4.156:2379" \
cluster-health
4.3 安装运行Master节点组件
- 下载组件:
[root@ k8s-master ~]#wget https://dl.k8s.io/v1.18.8/kubernetes-server-linux-amd64.tar.gz
- 解压组件包:
[root@k8s-master ~]# tar zxvf kubernetes-server-linux-amd64.tar.gz
[root@k8s-master ~]#mkdir /opt/kubernetes/{bin,cfg,ssl,logs} -p
[root@k8s-master ~]#cp kubernetes/server/bin/{kube-apiserver,kube-scheduler,kube-controller-manager,kubectl,kubelet} /opt/kubernetes/bin
- 生成证书
创建CA证书:
[root@k8s-master ~]# vim ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
[root@k8s-master ~]#vim ca-csr.json
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing",
"O": "k8s",
"OU": "System"
}
]
}
[root@k8s-master ~]#cfssl gencert -initca ca-csr.json | cfssljson -bare ca –
生成apiserver证书:
[root@k8s-master ~]#vim server-csr.json
{
"CN": "kubernetes",
"hosts": [
"10.0.0.1",//这是后面dns要使用的虚拟网络的网关,不用改,就用这个 切忌(删除这行)
"127.0.0.1",
"192.168.4.154",
"192.168.4.155",
"192.168.4.156",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
[root@k8s-master ~]#cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server
生成kube-proxy证书:
[root@k8s-master ~]#vim kube-proxy-csr.json
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
[root@k8s-master ~]#cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
最终生成以下证书文件:
[root@k8s-master ~]## ls *pem
ca-key.pem ca.pem kube-proxy-key.pem kube-proxy.pem server-key.pem server.pem
如果有多个master,需要将证书拷贝到所有的 master节点:
[root@k8s-master ~]#scp server.pem server-key.pem ca.pem ca-key.pem k8s-master2:/opt/kubernetes/ssl/
创建token文件:
#生成随机token
[root@k8s-master ~]#head -c 16 /dev/urandom | od -An -t x | tr -d ' '
[root@k8s-master ~]#cat << EOF >/opt/kubernetes/cfg/token.csv
79d370bf4b3e1bda79087504d34b9e5d,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
第一列:随机字符串,自己可生成,第二列:用户名,第三列:UID,第四列:用户组
- 配置apiserver
创建配置文件:
[root@k8s-master~]# vim /opt/kubernetes/cfg/kube-apiserver
KUBE_APISERVER_OPTS="--logtostderr=true \
--v=4 \
--log-dir=/opt/kubernetes/logs \
--etcd-servers=https://192.168.4.154:2379,https://192.168.4.155:2379,https://192.168.4.156:2379 \
--bind-address=192.168.4.154 \
--secure-port=6443 \
--advertise-address=192.168.4.154 \
--allow-privileged=true \
--service-cluster-ip-range=10.0.0.0/24 \
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \
--authorization-mode=RBAC,Node \
--enable-bootstrap-token-auth \
--token-auth-file=/opt/kubernetes/cfg/token.csv \
--service-node-port-range=30000-50000 \
--tls-cert-file=/opt/kubernetes/ssl/server.pem \
--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \
--client-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \
--etcd-cafile=/opt/etcd/ssl/ca.pem \
--etcd-certfile=/opt/etcd/ssl/server.pem \
--etcd-keyfile=/opt/etcd/ssl/server-key.pem"
配置好前面生成的证书,确保能连接etcd。
参数说明:
* --logtostderr 启用日志
* --v 日志等级
* --etcd-servers etcd集群地址
* --bind-address 监听地址
* --secure-port https安全端口
* --advertise-address 集群通告地址
* --allow-privileged 启用授权
* --service-cluster-ip-range Service虚拟IP地址段
* --enable-admission-plugins 准入控制模块
* --authorization-mode 认证授权,启用RBAC授权和节点自管理
* --enable-bootstrap-token-auth 启用TLS bootstrap功能,后面会讲到
* --token-auth-file token文件
* --service-node-port-range Service Node类型默认分配端口范围
创建systemd服务文件:
[root@k8s-master~]#vim /usr/lib/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-apiserver
ExecStart=/opt/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
启动服务,并设置开机启动:
[root@k8s-master~]#systemctl daemon-reload
[root@k8s-master~]#systemctl enable kube-apiserver
[root@k8s-master~]#systemctl restart kube-apiserver
注意:apiserver默认支持etcd3,如果是etcd2,需启动时指定版本选项–storage-backend=etcd2
- 配置scheduler
创建配置文件:
[root@k8s-master~]#cat << EOF >/opt/kubernetes/cfg/kube-scheduler
KUBE_SCHEDULER_OPTS="--logtostderr=true \
--v=4 \
--log-dir=/opt/kubernetes/logs \
--master=127.0.0.1:8080 \
--leader-elect"
EOF
参数说明:
* --master 连接本地apiserver
* --leader-elect 当该组件启动多个时,自动选举(HA)
创建systemd服务文件:
[root@k8s-master~]#vim /usr/lib/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-scheduler
ExecStart=/opt/kubernetes/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
启动服务,并设置开机启动:
[root@k8s-master~]#systemctl daemon-reload
[root@k8s-master~]#systemctl enable kube-scheduler
[root@k8s-master~]#systemctl restart kube-scheduler
- 配置controller-manager
创建配置文件:
[root@k8s-master~]# vim /opt/kubernetes/cfg/kube-controller-manager
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=true \
--v=4 \
--log-dir=/opt/kubernetes/logs \
--master=127.0.0.1:8080 \
--leader-elect=true \
--address=127.0.0.1 \
--service-cluster-ip-range=10.0.0.0/24 \
--cluster-name=kubernetes \
--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem \
--root-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem"
创建systemd服务文件:
[root@k8s-master~]#vim /usr/lib/systemd/system/kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-controller-manager
ExecStart=/opt/kubernetes/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
启动服务,并设置开机启动:
[root@k8s-master~]#systemctl daemon-reload
[root@k8s-master~]#systemctl enable kube-controller-manager
[root@k8s-master~]#systemctl restart kube-controller-manager
注意:几个组件启动顺序有依赖,需要先启动etcd,再启动apiserver,其他组件无顺序要求
所有组件都已经启动成功,通过kubectl工具查看当前集群组件状态:
[root@k8s-master~]# ln -s /opt/kubernetes/bin/kubectl /usr/bin/
[root@k8s-master~]# kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
etcd-0 Healthy {"health":"true"}
etcd-2 Healthy {"health":"true"}
etcd-1 Healthy {"health":"true"}
controller-manager Healthy ok
如上输出说明组件都正常。
- 查看启动日志的方法
[root@k8s-master~]# journalctl -u kube-apiserver
将kubelet-bootstrap用户绑定到系统集群角色
[root@k8s-master~]#/opt/kubernetes/bin/kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap
创建kubeconfig文件:
在生成kubernetes证书的目录下执行以下命令生成kubeconfig文件:
指定apiserver 地址(如果apiserver做了负载均衡,则填写负载均衡地址)
KUBE_APISERVER="https://192.168.4.154:6443"
BOOTSTRAP_TOKEN=79d370bf4b3e1bda79087504d34b9e5d
设置集群参数
[root@k8s-master~] #/opt/kubernetes/bin/kubectl config set-cluster kubernetes \
--certificate-authority=./ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=bootstrap.kubeconfig
设置客户端认证参数
[root@k8s-master~]#/opt/kubernetes/bin/kubectl config set-credentials kubelet-bootstrap \
--token=${BOOTSTRAP_TOKEN} \
--kubeconfig=bootstrap.kubeconfig
设置上下文参数
[root@k8s-master~]#/opt/kubernetes/bin/kubectl config set-context default \
--cluster=kubernetes \
--user=kubelet-bootstrap \
--kubeconfig=bootstrap.kubeconfig
设置默认上下文
[root@k8s-master~]#/opt/kubernetes/bin/kubectl config use-context default --kubeconfig=bootstrap.kubeconfig
创建kube-proxy kubeconfig文件
[root@k8s-master~]#/opt/kubernetes/bin/kubectl config set-cluster kubernetes \
--certificate-authority=./ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=kube-proxy.kubeconfig
[root@k8s-master~]#/opt/kubernetes/bin/kubectl config set-credentials kube-proxy \
--client-certificate=./kube-proxy.pem \
--client-key=./kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig
[root@k8s-master~]#/opt/kubernetes/bin/kubectl config set-context default \
--cluster=kubernetes \
--user=kube-proxy \
--kubeconfig=kube-proxy.kubeconfig
[root@k8s-master~]#/opt/kubernetes/bin/kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
[root@k8s-master~]# ls
bootstrap.kubeconfig kube-proxy.kubeconfig
注:将这两个文件拷贝到Node节点/opt/kubernetes/cfg目录下。
4.4 安装运行Node节点组件
- 下载组件
[root@k8s-node01 ~]#wget https://dl.k8s.io/v1.18.8/kubernetes-client-linux-amd64.tar.gz
- 解压组件包:
[root@k8s-node01 ~]#tar zxvf kubernetes-client-linux-amd64.tar.gz
[root@k8s-node01 ~]#cp kubernetes/client/bin/kubectl /opt/kubernetes/bin/
[root@k8s-node01 ~]#mkdir -p /opt/kubernetes/{bin,cfg,ssl}
[root@k8s-node01 ~]#scp root@192.168.4.154:/root/kubernetes/server/bin/{kubelet,kube-proxy} /opt/kubernetes/bin/
- 配置kubelet
创建kubelet配置文件:
[root@k8s-node01 ~]# cat << EOF >/opt/kubernetes/cfg/kubelet
KUBELET_OPTS="--logtostderr=true \
--v=4 \
--log-dir=/opt/kubernetes/logs \
--hostname-override=192.168.4.155 \
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \
--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \
--config=/opt/kubernetes/cfg/kubelet.config \
--cert-dir=/opt/kubernetes/ssl \
--network-plugin=cni \
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"
EOF
参数说明:
* --hostname-override 在集群中显示的主机名
* --kubeconfig 指定kubeconfig文件位置,会自动生成
* --bootstrap-kubeconfig 指定刚才生成的bootstrap.kubeconfig文件
* --cert-dir 颁发证书存放位置
* --pod-infra-container-image 管理Pod网络的镜像
创建kube.config配置文件:
[root@ k8s-node01 ~]# cat << EOF > /opt/kubernetes/cfg/kubelet.config
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 192.168.4.155
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS: ["10.0.0.2"]
clusterDomain: cluster.local.
failSwapOn: false
authentication:
anonymous:
enabled: true
webhook:
enabled: false
EOF
创建systemd服务文件:
[root@k8s-node01 ~]#vim /usr/lib/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kubelet
ExecStart=/opt/kubernetes/bin/kubelet $KUBELET_OPTS
Restart=on-failure
KillMode=process
[Install]
WantedBy=multi-user.target
启动服务,并设置开机启动:
[root@k8s-node01 ~]#systemctl daemon-reload
[root@k8s-node01 ~]#systemctl enable kubelet
[root@k8s-node01 ~]#systemctl restart kubelet
在Master审批Node加入集群:
启动后还没加入到集群中,需要手动允许该节点才可以。在Master节点查看请求签名的Node:
[root@k8s-master~]# /opt/kubernetes/bin/kubectl get csr
[root@k8s-master~]#/opt/kubernetes/bin/kubectl certificate approve XXXXID
[root@k8s-master~]#/opt/kubernetes/bin/kubectl get node
- 配置kube-proxy
创建kube-proxy配置文件:
[root@k8s-node01 ~]#vim /opt/kubernetes/cfg/kube-proxy
KUBE_PROXY_OPTS="--logtostderr=true \
--v=4 \
--log-dir=/opt/kubernetes/logs \
--hostname-override=192.168.4.155 \
--cluster-cidr=10.0.0.0/24 \ //不要改,就是这个ip
--kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig"
创建systemd服务文件:
[root@k8s-node01 ~]# vim /usr/lib/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
EnvironmentFile=-/opt/kubernetes/cfg/kube-proxy
ExecStart=/opt/kubernetes/bin/kube-proxy $KUBE_PROXY_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
启动服务,并设置开机启动:
[root@k8s-node01 ~]#systemctl daemon-reload
[root@k8s-node01 ~]#systemctl enable kube-proxy
[root@k8s-node01 ~]#systemctl restart kube-proxy
注意:其他节点加入集群与k8s-node01方式相同,但需修改kubelet的–address和–hostname-override选项为本机IP。
查看集群状态
[root@k8s-master~]# /opt/kubernetes/bin/kubectl get node
[root@k8s-master~]# /opt/kubernetes/bin/kubectl get cs
查看启动日志的方法
[root@k8s-master~]# journalctl -u kubelet
4.5 部署Flannel网络
- 下载组件并定义网段
flannel要用etcd存储自身一个子网信息,所以要保证能成功连接etcd,写入预定义子网段:
[root@k8s-master ~]#wget https://github.com/coreos/flannel/releases/download/v0.12.0/flannel-v0.12.0-linux-amd64.tar.gz
[root@k8s-master ~]#/opt/etcd/bin/etcdctl \
--ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem \
--endpoints="https://192.168.4.154:2379,https://192.168.4.155:2379,https://192.168.4.156:2379" \
set /coreos.com/network/config '{ "Network": "172.17.0.0/16", "Backend": {"Type": "vxlan"}}'
以下部署步骤在每个node节点都操作
- 下载二进制包:
#wget https://github.com/coreos/flannel/releases/download/v0.12.0/flannel-v0.12.0-linux-amd64.tar.gz
mkdir -pv /opt/kubernetes/bin
tar -zxvf flannel-v0.12.0-linux-amd64.tar.gz
mv flanneld mk-docker-opts.sh /opt/kubernetes/bin
- 配置Flannel:
# mkdir -p /opt/kubernetes/cfg/
# vim /opt/kubernetes/cfg/flanneld
FLANNEL_OPTIONS="--etcd-endpoints=https://192.168.4.154:2379,https://192.168.4.155:2379, https://192.168.4.156:2379 \
--etcd-cafile=/opt/etcd/ssl/ca.pem \
--etcd-certfile=/opt/etcd/ssl/server.pem \
--etcd-keyfile=/opt/etcd/ssl/server-key.pem \
--log-dir=/opt/kubernetes/logs "
- systemd管理Flannel:
# vi /usr/lib/systemd/system/flanneld.service
[Unit]
Description=Flanneld overlay address etcd agent
After=network-online.target network.target
Before=docker.service
[Service]
Type=notify
EnvironmentFile=/opt/kubernetes/cfg/flanneld
ExecStart=/opt/kubernetes/bin/flannel $FLANNEL_OPTIONS --ip-masq=true --etcd-prefix=/coreos.com/network
ExecStartPost=/opt/kubernetes/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.env
Restart=on-failure
[Install]
WantedBy=multi-user.target
- 配置Docker启动指定子网段:
#vi /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=/run/flannel/subnet.env
ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
- 从其他节点拷贝证书文件到node1和node2上:flanel需要证书
scp /opt/etcd/ssl/* k8s-node1:/opt/etcd/ssl/
- 重启flannel和docker:
systemctl daemon-reload
systemctl restart flanneld
systemctl enable flanneld
systemctl restart docker
- 检查是否生效:
#ps -ef |grep docker
root 20941 1 1 Jun28 ? 09:15:34 /usr/bin/dockerd --bip=172.17.34.1/24 --ip-masq=false --mtu=1450
#ip addr
3607: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN
link/ether 8a:2e:3d:09:dd:82 brd ff:ff:ff:ff:ff:ff
inet 172.17.34.0/32 scope global flannel.1
valid_lft forever preferred_lft forever
3608: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP
link/ether 02:42:31:8f:d3:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.34.1/24 brd 172.17.34.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:31ff:fe8f:d302/64 scope link
valid_lft forever preferred_lft forever
确保docker0与flannel.1在同一网段。
测试不同节点互通,在当前节点访问另一个Node节点docker0 IP:
[root@k8s-master ~]## ping 172.17.58.1
PING 172.17.58.1 (172.17.58.1) 56(84) bytes of data.
64 bytes from 172.17.58.1: icmp_seq=1 ttl=64 time=0.263 ms
64 bytes from 172.17.58.1: icmp_seq=2 ttl=64 time=0.204 ms
如果能通说明Flannel部署成功。如果不通检查下日志:journalctl -u flannel
4.6 部署Calico网络
- 关闭Flannel服务(在各node节点)
[root@k8s-node1 ~]# systemctl stop flanneld
[root@k8s-node1 ~]#systemctl disable flanneld
[root@k8s-node1 ~]# systemctl status flanneld
- 重启所有节点
- 下载官方yaml文件(在Master节点操作)
# wget https://docs.projectcalico.org/manifests/calico-etcd.yaml
# mv calico-etcd.yaml calico.yaml
- 配置calico
calico# vim calico.yaml
data:
# Configure this with the location of your etcd cluster.
etcd_endpoints: " https://192.168.4.154:2379,https://192.168.4.155:2379,https://192.168.4.156:2379"
# If you're using TLS enabled etcd uncomment the following.
# You must also populate the Secret below with these files.
etcd_ca: "/calico-secrets/etcd-ca" #取消原来的注释即可
etcd_cert: "/calico-secrets/etcd-cert"
etcd_key: "/calico-secrets/etcd-key"
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: calico-etcd-secrets
namespace: kube-system
data:
etcd-key: (cat /etc/kubernetes/ssl/etcd-key.pem | base64 | tr -d '\n') #将输出结果填写在这里
etcd-cert: (cat /etc/kubernetes/ssl/etcd.pem | base64 | tr -d '\n') #将输出结果填写在这里
etcd-ca: (cat /etc/kubernetes/ssl/ca.pem | base64 | tr -d '\n') #将输出结果填写在这里
#如果etcd没用启用tls则为null
#上面是必须要修改的参数,文件中有一个参数是设置pod network地址的,根据实际情况做修改:
- name: CALICO_IPV4POOL_CIDR
value: "10.37.0.0/16"
- 修改kubelet配置
设置各node上Kubelet服务的启动参数: –network-plugin=cni,
设置 master上的kube-apiserver服务的启动参数: –allow-privileged=true (因为calico-node需要以特权模式运行在各node上)
设置好后,重新启动kubelet。
这样通过calico就完成了Node间容器网络的设置 ,在后续的pod创建过程中,Kubelet将通过CNI接口调用 calico进行Pod的网络设置包括IP地址,路由规则,Iptables规则
- 验证各Node间网络联通性:
kubelet启动后主机上就生成了一个tunl0接口。
#第一台Node查看:
[root@k8s-node1 ~]#ip route
172.16.169.128/26 via 192.168.4.156 dev tunl0 proto bird onlink
#第二台Node查看:
[root@k8s-node1 ~]#ip route
172.16.36.64/26 via 192.168.4.155 dev tunl0 proto bird onlink
#每台node上都自动设置了到其它node上pod网络的路由,去往其它节点的路都是通过tunl0接口,这就是IPIP模式。
如果设置CALICO_IPV4POOL_IPIP=”off” ,即不使用IPIP模式,则Calico将不会创建tunl0网络接口,路由规则直接使用物理机网卡作为路由器转发。
4.7 部署WebUI
- 下载官方的yaml文件
[root@k8s-master~]#wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml
- 修改recommended.yaml
修改Service的NodePort便于我们从集群外使用浏览器访问dashboard
service段配置更改如下:(NodePort: 30001可以省略,缺省则为随机端口)
- 执行安装
[root@k8s-master~]# kubectl create -f recommended.yaml
- 创建 serviceaccount
[root@k8s-master~]# vi dashboard-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: dashboard-admin
namespace: kubernetes-dashboard
- 执行安装
[root@k8s-master~]# kubectl create -f dashboard-sa.yaml
- 创建clusterrolebinding为dashboard sa授权集群权限cluster-admin
[root@k8s-master~]# vi dashboard-clusterrolebinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: dashboard-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: dashboard-admin
namespace: kubernetes-dashboard
- 执行安装
[root@k8s-master~]# kubectl create -f dashboard-clusterrolebinding
- 获取token
[root@k8s-master~]# kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
- 查看NodePort端口
如果按上面在NodePort配置成固定端口,就直接用固定端口访问即可
- 访问页面
5 结果验证
运行一个测试示例,创建一个Nginx Web,判断集群是否正常工作:
- 创建nginx.yaml
[root@k8s-master~]#vi nginx.yaml
# API 版本号
apiVersion: apps/v1
# 类型,如:Pod/ReplicationController/Deployment/Service/Ingress
kind: Deployment
metadata:
# Kind 的名称
name: nginx-app
spec:
selector:
matchLabels:
# 容器标签的名字,发布 Service 时,selector 需要和这里对应
app: nginx
# 部署的实例数量
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
# 配置容器,数组类型,说明可以配置多个容器
containers:
# 容器名称
- name: nginx
# 容器镜像
image: nginx:1.17
# 只有镜像不存在时,才会进行镜像拉取
imagePullPolicy: IfNotPresent
ports:
# Pod 端口
- containerPort: 80
- 创建pods:
[root@k8s-master~]#kubectl apply -f nginx.yaml
- 查看pod详细信息:
[root@k8s-master~]# kubectl get pods
[root@k8s-master~]# kubectl get deployment
- 暴露服务:
[root@k8s-master~]# kubectl expose deployment nginx-app --port=80 --type=LoadBalancer
- 查看服务状态(查看对外的端口):
[root@k8s-master~]# kubectl get services
- 浏览器校验
- 删除pods
先删除pod
再删除对应的deployment
6 参考资料
- https://www.kubernetes.org.cn/k8s
- https://www.jianshu.com/p/4c870654200e
- https://github.com/kubernetes/dashboard
- https://docs.projectcalico.org/
如有其它问题,请填写右侧需求表单联系我们。www.asterfusion.com