二进制部署k8s
1.介绍
- k8s是谷歌开源容器集群管理系统,它可以应用于程序部署扩展和管理,它提供了容器编排,资源调度,弹性伸缩,部署管理服务发现等一系列功能。
2.k8s的集群架构与组件
主节点Master运行着:API Server, scheduler, controller-manager三个节点
工作节点Node运行着:kubelet, kube-proxy
- Master组件
kube-apiserver
集群统一入口,各组件协调者,以restfulAPI提供接口服务,所有对象资源的增删改查和监听操作都交给APIServer处理后提交给ETCD存储。
kube-controller-manager
处理集群中常规后台任务,一个资源对应一个控制器,而ControllerManager就是负责管理这些控制器的
kube-scheduler
根据调度算法为新的创建Pod选择一个Node节点,可以任意部署,可以部署在一个节点上,也可以部署在不同节点上
etcd
分布式键值存储系统,用于保存集群状态数据,比如pod service等对象信息
- Node组件
kubelet
它是Master在Node节点上Agent,管理本机运行容器生命周期,比如:创建容器,Pod挂载卷,下载secret,获取若能国企和节点状态工作,kubelet将每个Pod转换成一组容器
kube-proxy
在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡
docker rocker
容器引擎,运行容器
3.K8s核心概念
-
Pod部署应用的最小单元
它是最小部署单元,它一组容器的集合,而且一个Pod中的可能有多个容器,容器之间网络是共享(当一个容器监听8080端口,其他的容器也能看见,并且通过k8s数据卷也能实现容器之间的数据的共享),而它们文件系统是隔离的。Pod是短暂的,当你触发服务更新或发布,那么之前pod就会销毁。
-
Controllers控制器
1.ReplicaSet: 确保预期的Pod副本数量
2.Deployment:用于无状态应用部署。
3.StatefulSet:用于有状态应用部署
4.DaemonSet:确保所有Node运行同一个Pod
5.Job:一次性任务。
6.Cronjob: 定时任务。
-
Service服务转发
1.防止Pod失去联系,定义一组Pod的访问策略
-
Label 标签
标签,附加在某个资源上,用于关联对象,查询和筛选。
-
Namespace
命名空间,将对象逻辑上隔离
什么是无状态应用和有状态的应用??
无状态:deployment
- 认为所有pod都是一样的,不具备与其他实例有不同的关系。
- 没有顺序的要求。
- 不用考虑再哪个Node运行。
- 随意扩容缩容。
有状态:SatefulSet
- 集群节点之间的关系。
- 数据不完全一致。
- 实例之间不对等的关系。
- 依靠外部存储的应用。
- 通过dns维持身份
像MySQl主从,Zookepeer
4.K8s部署前言:
-
官方提供的三种部署方式:
-
软件版本:
软件名称 版本号 Linux操作系统 CentOs7.5_x64 + Kubemetes 1.13 Etcd 3.+ Docker 18.+ Flannel 0.10 -
角色对应关系:
角色 | 部署IP | 组件 | ||
---|---|---|---|---|
k8s-master01 | 192.168.48.128 | kube-apiserver,kube-controller-manager,kube-scheduler,etcd | ||
k8s-node01 | 192.168.48.130 | kubelet,kube-proxy,docker,flannel,etcd | ||
k8s-node02 | 192.168.48.131 | kubelet, kube-proxy,docker,flannel,etcd |
- 部署架构图:
5.前续工作:
-
关闭各所有机器SELINUX和防火墙
vi /etc/selinux/config SELINUX=disabled setenforce 0 systemctl stop firewalld # 验证:iptables -vnL
-
修改主机名
# 192.168.48.128 改成 k8s-master01 vi /etc/hostname hostname k8s-master01 exit退出终端再进入。 以相同方式更改node01和node02的名字: # 192.168.48.130 改成 k8s-node01 # 192.168.48.131 改成 k8s-node02
6.HTTPS证书构建
-
因为apiServer 与 kubelet之间通信是https, etcd(数据库)与 Flannel之间通信也是https
-
自签SSL证书:我们需要构建2套证书,ca证书,和api-server证书。【ca.pem,server.pem代表证书, server-key代表私钥】
apiserver 加 ca-key.pem
-
为etcd生成证书
# 时间同步:(所有机器都同步) 下载ntpdate: yum install ntpdate 更新最新时间: ntpdate time.windows.com # 首先需要下载cfssl工具 执行脚本:[/root/k8s/etcd-cert:] bash cfssl.sh # 生成ca:# 执行下面命令会生成ca-config.json,ca-csr.json两个文件。 cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "www": { "expiry": "87600h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } } } EOF cat > ca-csr.json <<EOF { "CN": "etcd CA", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "Beijing", "ST": "Beijing" } ] } EOF # 生成根证书:initca 初始化ca-csr.json 配置文件 cfssl gencert -initca ca-csr.json | cfssljson -bare ca - # 生成etcd域名证书:配置部署etcd节点所有的IP cat > server-csr.json <<EOF { "CN": "etcd", "hosts": [ "192.168.48.128", "192.168.48.130", "192.168.48.131" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "ST": "BeiJing" } ] } EOF # 请求ca颁发证书: cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server # 此时会生成:server.pem 和 server-key.pem 而etcd使用这2个证书即可
7.ETCD数据库集群部署
- 准备工作
[root@k8s-master01 ~]# mkdir soft
[root@k8s-master01 ~]# cd soft/
# 解压之前下载好的etcd包:etcd-v3.3.10-linux-amd64.tar.gz
tar -zxvf etcd-v3.3.10-linux-amd64.tar.gz
[root@k8s-master01 soft]# cd etcd-v3.3.10-linux-amd64
[root@k8s-master01 etcd-v3.3.10-linux-amd64]# ls
Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
# etcd 启动etcd服务
# etcdctl 管理etcd客户端命令
# 创建etcd管理目录:
mkdir /opt/etcd/{cfg,bin,ssl} -p
# 将 etcd,etcdctl 移动到 /opt/etcd/bin
mv etcd etcdctl /opt/etcd/bin/
- etcd部署脚本(一般生产环境使用5台,但最小使用3台):
写etcd.sh脚本:
#!/bin/bash
# example: ./etcd.sh etcd01 192.168.1.10 etcd02=https://192.168.1.11:2380,etcd03=https://192.168.1.12:2380
ETCD_NAME=$1
ETCD_IP=$2
ETCD_CLUSTER=$3
# 工作目录定义
WORK_DIR=/opt/etcd
# 生成etcd配置文件
# Member中 2380端口设置集群之间通信,2379是数据传输端口
# Clustering 集群配置信息
cat <<EOF >$WORK_DIR/cfg/etcd
#[Member]
ETCD_NAME="${ETCD_NAME}"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://${ETCD_IP}:2380"
ETCD_LISTEN_CLIENT_URLS="https://${ETCD_IP}:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://${ETCD_IP}:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://${ETCD_IP}:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://${ETCD_IP}:2380,${ETCD_CLUSTER}"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF
# 配置证书选项
cat <<EOF >/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=${WORK_DIR}/cfg/etcd
ExecStart=${WORK_DIR}/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=${WORK_DIR}/ssl/server.pem
--key-file=${WORK_DIR}/ssl/server-key.pem
--peer-cert-file=${WORK_DIR}/ssl/server.pem
--peer-key-file=${WORK_DIR}/ssl/server-key.pem
--trusted-ca-file=${WORK_DIR}/ssl/ca.pem
--peer-trusted-ca-file=${WORK_DIR}/ssl/ca.pem
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
# 启动命令
systemctl daemon-reload
systemctl enable etcd
systemctl restart etcd
# 赋予执行权限
chmod +x etcd.sh
- 使用方式
./etcd.sh 当前节点名 当前节点ip 节点2的名=https://节点2的ip:2380,节点3的名=https://节点2的ip:2380
#示例:
./etcd.sh etcd01 192.168.48.128 etcd02=https://192.168.48.130:2380,etcd03=https://192.168.48.131:2380
# 执行脚本:
./etcd.sh etcd01 192.168.48.128 etcd02=https://192.168.48.130:2380,etcd03=https://192.168.48.131:2380
- 查看,检查配置文件:
#############################1#############################
cat /opt/etcd/cfg/etcd
#[Member]
ETCD_NAME="etcd01"# 当前节点名字
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.48.128:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.48.128:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.48.128:2380"# 2380端口设置集群之间通信
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.48.128:2379"# 2379是数据传输端口
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.48.128:2380,etcd02=https://192.168.48.130:2380,etcd03=https://192.168.48.131:2380"# 集群中节点
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"# token认证
ETCD_INITIAL_CLUSTER_STATE="new"# 代表新的集群
###############################2############################
cat /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
- 将证书拷贝到/opt/etcd/ssl
cp ~/k8s/etcd-cert/{ca,server-key,server}.pem /opt/etcd/ssl
ls /opt/etcd/ssl 查看证书
ca.pem server-key.pem server.pem
- 启动etcd
systemctl start etcd
- 查看启动日志:
tail /var/log/messages -f
- 将etcd配置拷贝其他2台机器上
scp -r /opt/etcd/ root@192.168.48.130:/opt/
scp -r /opt/etcd/ root@192.168.48.131:/opt/
- 将etcd.service拷贝到其他2台机器
scp /usr/lib/systemd/system/etcd.service root@192.168.48.130:/usr/lib/systemd/system
scp /usr/lib/systemd/system/etcd.service root@192.168.48.131:/usr/lib/systemd/system
- 修改192.168.48.130, 192.168.48.131配置文件
vim /opt/etcd/cfg/etcd
修改ETCD_NAME,ETCD_LISTEN_PEER_URLS, ETCD_LISTEN_CLIENT_URLS,ETCD_INITIAL_ADVERTISE_PEER_URLS,ETCD_ADVERTISE_CLIENT_URLS
- daemon-reload 和 启动
systemctl daemon-reload
systemctl start etcd
- 验证etcd集群状态
/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.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379" cluster-health
- 下面结果显示代表集群健康:
member 3f3868c5ec7337c4 is healthy: got healthy result from https://192.168.48.128:2379
member c3e65c73ad3cc87a is healthy: got healthy result from https://192.168.48.131:2379
member c4f45bf163b686e6 is healthy: got healthy result from https://192.168.48.130:2379
cluster is healthy
8.node安装docker
-
yum安装必要的组件
yum install -y yum-utils device-mapper-persistent-data lvm2
-
添加软件源信息
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
-
安装docker
yum -y install docker-ce
-
启动docker
systemctl start docker
-
daocloud配置docker加速器
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
-
重启docker
systemctl restart docker
9.Kubernetes网络模型(CNI)
-
CNI容器网络接口。Kubernetes网络模型设计基本要求:
1. 一个Pod一个ip 2. 每个Pod独立IP,Pod内所有容器共享网络(同一个IP) 3. 所有容器都可以与所有其他容器通信 4.所有节点都可以与所有容器通信
而实现上面要求实现方案为:隧道方案或路由方案,相比来说路由方案网络开销很小,常用实现组件:flannel和calico.flannel适用于小规模的,它局限于统一局域网之内,它对网络适应能力强。Calico基于BGP协议进行通信,它有很多网络通信是不支持的。大规模的适合calico,小规模适合flannel。
10.部署Kubernetes网络-Flannel
master节点
-
为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.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379" set /coreos.com/network/config '{"Network":"172.17.0.0/16", "Backend": {"Type": "vxlan"}}'
node节点
-
node节点创建工作目录
mkdir /opt/kubernetes/{bin,cfg,ssl} -p
-
下载flannel二进制包
flannel-v0.10.0-linux-amd64.tar.gz
-
解压flannel包
tar zxvf flannel-v0.10.0-linux-amd64.tar.gz
-
将解压生成的flanneld 和 mk-docker-opts.sh移动到/opt/kubernetes/bin/
mv flanneld mk-docker-opts.sh /opt/kubernetes/bin/
-
shell安装 flannel
# 生成flannel配置文件,指定使用etcd地址 cat <<EOF >/opt/kubernetes/cfg/flanneld FLANNEL_OPTIONS="--etcd-endpoints=${ETCD_ENDPOINTS} -etcd-cafile=/opt/etcd/ssl/ca.pem -etcd-certfile=/opt/etcd/ssl/server.pem -etcd-keyfile=/opt/etcd/ssl/server-key.pem" EOF # 生成flannel.service配置文件 cat <<EOF >/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/flanneld --ip-masq $FLANNEL_OPTIONS 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 EOF # 修改docker配置文件 cat <<EOF >/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 EOF systemctl daemon-reload systemctl enable flanneld systemctl restart flanneld systemctl restart docker
-
执行脚本,后面参数指定etcd的地址
./flannel.sh https://192.168.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379
-
查看flanneld配置是否生效
cat /opt/kubernetes/cfg/flanneld
-
查看flannel.service配置
cat /usr/lib/systemd/system/flanneld.service
-
启动flannel
systemctl start flanneld
-
查看启动状态
ps -ef | grep flannel
-
查看启动失败日志
tail /var/log/messages -f
-
重启docker,看是否引用flannel分配的子网
[root@k8s-node02 ~]# systemctl restart docker [root@k8s-node02 ~]# ps -ef | grep docker root 2613 1 1 23:25 ? 00:00:00 /usr/bin/dockerd --bip=172.17.44.1/24 --ip-masq=false --mtu=1450 root 2753 1351 0 23:26 pts/0 00:00:00 grep --color=auto docker # --bip看到引用的子网了,也可以用ifconfig查看docker0的ip
拷贝其他node节点拷贝
scp -r /opt/kubernetes/ root@192.168.48.131:/opt/
scp /usr/lib/systemd/system/{flanneld,docker}.service root@192.168.48.131:/usr/lib/systemd/system
# 启动flannel
systemctl start flannel
# 重启docker
systemctl restart docker
验证:
在node1运行容器并进入:docker run -it busybox
ifconfig查看容器ip
在node2 去 ping 该ip看是否通
在node1与node2的容器内互相ping
- etcd查看运行node节点
[root@k8s-master01 k8s]# /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.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379" get /coreos.com/network/subnets
/coreos.com/network/subnets: is a directory
[root@k8s-master01 k8s]# /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.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379" ls /coreos.com/network/subnets/
/coreos.com/network/subnets/172.17.68.0-24
/coreos.com/network/subnets/172.17.44.0-24
[root@k8s-master01 k8s]# /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.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379" get /coreos.com/network/subnets/172.17.68.0-24
{"PublicIP":"192.168.48.130","BackendType":"vxlan","BackendData":{"VtepMAC":"5a:5f:22:12:e8:62"}}
11.k8s Master组件部署
11.1api-server
- 官网下载kubernetes包,上传master服务端
kubernetes-server-linux-amd64.tar.gz 1.13版本
- 解压kubernetes-server包
tar zxvf kubernetes-server-linux-amd64.tar.gz
- master创建kubernetes管理目录
mkdir -p /opt/kubernetes/{bin,cfg,ssl}
- cd到解压后kubernetes/server/bin中
cd kubernetes/server/bin
- 将kube-apiserver kube-controller-manager kube-scheduler 拷贝到 /opt/kubernetes/bin下
cp kube-apiserver kube-controller-manager kube-scheduler /opt/kubernetes/bin/
- 编写apiserver.sh脚本
#!/bin/bash
MASTER_ADDRESS=$1# 指定当前apiserver地址
ETCD_SERVERS=$2# 指定etcd地址
# 生成apiserver配置文件
cat <<EOF >/opt/kubernetes/cfg/kube-apiserver
KUBE_APISERVER_OPTS="--logtostderr=false \
--log-dir=/opt/kubernetes/logs \# 日志目录
--v=4 \#日志级别
--etcd-servers=${ETCD_SERVERS} \# etcd-server地址
--bind-address=${MASTER_ADDRESS} \#绑定ip地址
--secure-port=6443 \#apiserver 地址
--advertise-address=${MASTER_ADDRESS} \# 集群通告地址
--allow-privileged=true \# 授权是否允许(容器层面的)
--service-cluster-ip-range=10.0.0.0/24 \# 指定负载均衡ip
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \# 启用准入插件
--authorization-mode=RBAC,Node \#认证模式
--kubelet-https=true \# 启用https
--enable-bootstrap-token-auth \#认证用的
--token-auth-file=/opt/kubernetes/cfg/token.csv \#token文件
--service-node-port-range=30000-50000 \# 端口范围
--tls-cert-file=/opt/kubernetes/ssl/server.pem \#配置apiserver证书路径
--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \
--client-ca-file=/opt/kubernetes/ssl/ca.pem \#配置ca证书
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \
--etcd-cafile=/opt/etcd/ssl/ca.pem \# etcd的ca证书
--etcd-certfile=/opt/etcd/ssl/server.pem \
--etcd-keyfile=/opt/etcd/ssl/server-key.pem"
EOF
# 生成 apiserver.service 配置文件
cat <<EOF >/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
EOF
systemctl daemon-reload
systemctl enable kube-apiserver
systemctl restart kube-apiserver
- 创建日志目录
mkdir /opt/kubernetes/logs
- 启动apiserver.sh脚本
./apiserver.sh 当前master地址 etcd地址
./apiserver.sh 192.168.48.128 https://192.168.48.128:2379,https://192.168.48.130:2379,https://192.168.48.131:2379
- 查看apiserver配置文件是否生效
cat /opt/kubernetes/cfg/kube-apiserver
- k8s证书生成
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
cat > ca-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
#-----------------------
cat > server-csr.json <<EOF
{
"CN": "kubernetes",
"hosts": [
"10.0.0.1",
"127.0.0.1",
"192.168.48.128",# 这里写master的ip , LB的ip,也可多写几个ip备用,node节点可以不用写
"192.168.48.129",
"192.168.48.132",
"192.168.48.133",
"192.168.48.134",
"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"
}
]
}
EOF
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server
#-----------------------
# 访问k8s集群时候会用到证书
cat > admin-csr.json <<EOF
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
EOF
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
#-----------------------
# kube-proxy证书
cat > kube-proxy-csr.json <<EOF
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
- 执行脚本
bash k8s-cert.sh
- 将 ca.pem server.pem server-key.pem 放到 /opt/kubernetes/ssl/
cp ca-key.pem ca.pem server.pem server-key.pem /opt/kubernetes/ssl/
- 生成token
BOOTSTRAP_TOKEN=0fb61c46f8991b718eb38d27b605b008
cat > token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
- 查看token.csv
[root@k8s-master01 k8s-cert]# cat token.csv
0fb61c46f8991b718eb38d27b605b008,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
# token的ip 标识用户 #用户组 # 加入k8s角色
- 移动token.csv 到/opt/kubernetes/cfg/
mv token.csv /opt/kubernetes/cfg/
- 启动apiserver
systemctl start kube-apiserver
- 查看是否启动
ps -ef | grep kube-apiserver
- 若没有正常启动采用手动启动排查问题
source /opt/kubernetes/cfg/kube-apiserver
/opt/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
11.2controller-manager
-
api-server 默认本地监听8080和6443,通过下列指令查看端口
netstat -antp | grep 8080 netstat -antp | grep 6443
-
编写脚本controller-manager.sh
#!/bin/bash
# api-server的地址
MASTER_ADDRESS=$1
cat <<EOF >/opt/kubernetes/cfg/kube-controller-manager
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=true \
--v=4 \
--master=${MASTER_ADDRESS}:8080 \# 本地启动ip端口
--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 \
--experimental-cluster-signing-duration=87600h0m0s"
EOF
cat <<EOF >/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
EOF
systemctl daemon-reload
systemctl enable kube-controller-manager
systemctl restart kube-controller-manager
- 运行脚本
./controller-manager.sh 本地ip
./controller-manager.sh 127.0.0.1
- 验证
cat /opt/kubernetes/cfg/kube-controller-manager
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=true
--v=4
--master=127.0.0.1:8080 # 本地启动ip端
--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
--experimental-cluster-signing-duration=87600h0m0s" #为k8s办法证书时间
- 也可将日志文件修改指定文件:
vi /opt/kubernetes/cfg/kube-controller-manager
# 修改 --logtostderr=false
# 修改 --log-dir=指定日志目录,需之前创建好
11.3 scheduler
- 编写脚本scheduler.sh
#!/bin/bash
MASTER_ADDRESS=$1
cat <<EOF >/opt/kubernetes/cfg/kube-scheduler
KUBE_SCHEDULER_OPTS="--logtostderr=true \
--v=4 \
--master=${MASTER_ADDRESS}:8080 \
--leader-elect"
EOF
cat <<EOF >/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
EOF
systemctl daemon-reload
systemctl enable kube-scheduler
systemctl restart kube-scheduler
- 运行脚本
./scheduler.sh 本地ip
./scheduler.sh 127.0.0.1
- 验证
[root@k8s-master01 k8s]# cat /opt/kubernetes/cfg/kube-scheduler
KUBE_SCHEDULER_OPTS="--logtostderr=true
--v=4
--master=127.0.0.1:8080
--leader-elect"
11.4查看集群状态
- 将管理k8s集群的工具kubectl拷贝到/usr/bin下方便使用
cp /root/soft/kubernetes/server/bin/kubectl /usr/bin/
- 查看etcd集群,scheduler,controller-manager状态
kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-2 Healthy {"health":"true"}
etcd-1 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}
12.k8s 中node部署
- 在Master中,将之前生成token.csv中定义kubelet-bootstrap用户绑定到系统集群角色
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
删除角色名字: kubectl delete clusterrolebinding kubelet-bootstrap [clusterrolebinding kubelet-bootstrap为角色名字]
- Master创建kubeconfig.sh,生成证书,它用于存放连接apiserver的信息
APISERVER=$1# 指定apiserver的ip
SSL_DIR=$2# ssl证书目录
BOOTSTRAP_TOKEN=0fb61c46f8991b718eb38d27b605b008
# 创建kubelet bootstrapping kubeconfig
export KUBE_APISERVER="https://$APISERVER:6443"
# 设置集群参数
kubectl config set-cluster kubernetes
--certificate-authority=$SSL_DIR/ca.pem
--embed-certs=true
--server=${KUBE_APISERVER}
--kubeconfig=bootstrap.kubeconfig
# 设置客户端认证参数
kubectl config set-credentials kubelet-bootstrap
--token=${BOOTSTRAP_TOKEN}
--kubeconfig=bootstrap.kubeconfig
# 设置上下文参数
kubectl config set-context default
--cluster=kubernetes
--user=kubelet-bootstrap
--kubeconfig=bootstrap.kubeconfig
# 设置默认上下文
kubectl config use-context default --kubeconfig=bootstrap.kubeconfig
#----------------------
# 创建kube-proxy kubeconfig文件
kubectl config set-cluster kubernetes
--certificate-authority=$SSL_DIR/ca.pem
--embed-certs=true
--server=${KUBE_APISERVER}
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-credentials kube-proxy
--client-certificate=$SSL_DIR/kube-proxy.pem
--client-key=$SSL_DIR/kube-proxy-key.pem
--embed-certs=true
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-context default
--cluster=kubernetes
--user=kube-proxy
--kubeconfig=kube-proxy.kubeconfig
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
- 运行脚本
bash kubeconfig.sh apiserver的ip ssl证书目录
bash kubeconfig.sh 192.168.48.128 /root/k8s/k8s-cert
- 此时生成有2个带kubeconfig后缀文件
kube-proxy.kubeconfig
bootstrap.kubeconfig
- 拷贝kube-proxy.kubeconfig, bootstrap.kubeconfig到node节点上
scp kube-proxy.kubeconfig bootstrap.kubeconfig root@192.168.48.130:/opt/kubernetes/cfg/
scp kube-proxy.kubeconfig bootstrap.kubeconfig root@192.168.48.131:/opt/kubernetes/cfg/
- Master中 /root/soft/kubernetes/server/bin/拷贝kubelet,kube-proxy拷贝到node节点上
scp kubelet kube-proxy root@192.168.48.130:/opt/kubernetes/bin
scp kubelet kube-proxy root@192.168.48.131:/opt/kubernetes/bin
kubelet.sh
- node编写脚本kubelet.sh
#!/bin/bash
NODE_ADDRESS=$1# 指定当前节点ip
DNS_SERVER_IP=${2:-"10.0.0.2"}#部署dns使用ip
# kubelet配置文件
cat <<EOF >/opt/kubernetes/cfg/kubelet
KUBELET_OPTS="--logtostderr=false \
--log-dir=/opt/kubernetes/logs \
--v=4 \
--address=${NODE_ADDRESS} \
--hostname-override=${NODE_ADDRESS} \
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \
--experimental-bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \
--config=/opt/kubernetes/cfg/kubelet.config \
--cert-dir=/opt/kubernetes/ssl \
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"
EOF
# kubelet.config 配置文件
cat <<EOF >/opt/kubernetes/cfg/kubelet.config
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: ${NODE_ADDRESS}
port: 10250
cgroupDriver: cgroupfs
clusterDNS:
- ${DNS_SERVER_IP}
clusterDomain: cluster.local.
failSwapOn: false
EOF
# kubelet.service配置文件
cat <<EOF >/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
EOF
systemctl daemon-reload
systemctl enable kubelet
systemctl restart kubelet
- node执行脚本kubelet.sh
bash kubelet.sh node节点ip
bash kubelet.sh 192.168.48.130
- 查看配置
[root@k8s-node01 ~]# cat /opt/kubernetes/cfg/kubelet
KUBELET_OPTS="--logtostderr=false # 指定日志目录
--log-dir=/opt/kubernetes/logs
--v=4
--address=192.168.48.130
--hostname-override=192.168.48.130 # 当前主机名
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig # kubernetes自动生成
--experimental-bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig #bootstrap
--config=/opt/kubernetes/cfg/kubelet.config # 配置信息
--cert-dir=/opt/kubernetes/ssl # 证书
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"# 创建pod第一个容器引入镜像地址
- 启动异常,可以查看系统日志
less /opt/kubernetes/logs/kubelet.INFO
less /var/log/messages -f
- 或是kubelet日志
journalctl -u kubelet
- 可能出现报错
failed to run Kubelet: cannot create certificate signing request: certificatesigningrequests.certificates.k8s.io is forbidden: User "kubelet-bootstrap" cannot create resource "certificatesigningrequests" in API group "certificates.k8s.io" at the cluster scope
创建用户绑定到系统集群角色是否正确???
删除角色名字: kubectl delete clusterrolebinding kubelet-bootstrap
重新创建:kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
# 之前把node-bootstrapper 写成 nodebootstrapper
- 查看启动状态
systemctl restart kubelet
- 启动成功后会向Master发送请求证书。在Master中执行如下命令查看请求签名
kubectl get csr
NAME AGE REQUESTOR CONDITION
node-csr-Ddql46qTy-HKhQ5ejzeGKpbbugXDII22zTLgRg4hFt0 4m29s kubelet-bootstrap Pending
- Master颁发证书
kubectl certificate approve [NAME]
kubectl certificate approve node-csr-Ddql46qTy-HKhQ5ejzeGKpbbugXDII22zTLgRg4hFt0
- 查看节点:
kubectl get node
proxy.sh
- 编写proxy.sh脚本
#!/bin/bash
NODE_ADDRESS=$1
cat <<EOF >/opt/kubernetes/cfg/kube-proxy
KUBE_PROXY_OPTS="--logtostderr=true \
--v=4 \
--hostname-override=${NODE_ADDRESS} \# 节点名字
--cluster-cidr=10.0.0.0/24 \# 集群网段
--proxy-mode=ipvs \# ipvs模式
--kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig"
EOF
cat <<EOF >/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
EOF
systemctl daemon-reload
systemctl enable kube-proxy
systemctl restart kube-proxy
- 执行脚本
bash proxy.sh 192.168.48.130
- 查看启动状态
ps -ef | grep proxy
node的扩容
- 从已部署的node拷贝到其他node
scp -r /opt/kubernetes/ root@192.168.48.131:/opt/
scp /usr/lib/systemd/system/{kubelet,kube-proxy}.service root@192.168.48.131:/usr/lib/systemd/system/
- 在opt/kubernetes/cfg/目录下修改新node的ip
vi kubelet
--address,--hostname-override 改成本机IP
vi kubelet.config
address 改成本机IP
vi vi kube-proxy
--hostname-override 改成本机IP
- 删除拷贝过来办法的证书
cd /opt/kubernetes/ssl/
rm -f *
- 启动:
systemctl start kubelet
systemctl start kube-proxy
- Master颁发证书
kubectl certificate approve node-csr-gz_UlTpuBdk04IlNgwyC2MfVIhgRDso_xdS3ypGcxzs
- 查看节点
kubectl get node
13测试一下
# 创建一个nginx
kubectl create deployment nginx --image=nginx
# 暴漏应用 暴漏80端口
kubectl expose deployment nginx --port=80 --type=NodePort
[root@k8s-master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 15h
nginx NodePort 10.0.0.40 <none> 80:40009/TCP 21m
-
此时访问子节点
http://192.168.48.131:40009/
或http://192.168.48.130:40009/
就有nginx了 -
副本扩容
kubectl scale deployment nignx --replicas=3
-
此时查看
kubectl get pods
就会有三个nginx
14.dashboard可视化部署
-
先在node的节点上拉取镜像:
# node 节点拉取镜像 docker pull lizhenliang/kubernetes-dashboard-amd64:v1.10.1
-
拉取kubernetes-dashboard.yaml
wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
- 修改kubernetes-dashboard.yaml
vi kubernetes-dashboard.yaml
# 修改镜像地址
image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1 改为 image: lizhenliang/kubernetes-dashboard-amd64:v1.10.1
# 在Dashboard Service下spec新增type: NodePor 将其暴漏出来
# 并在ports新增一个端口 nodePort: 3000
# ------------------- Dashboard Service ------------------- #
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 30001
selector:
- 将修改的kubernetes-dashboard.yaml 应用
kubectl apply -f kubernetes-dashboard.yaml
- 查看运行
kubectl get pods -n kube-system
- 访问页面,因是https请求,它的证书不可信,所以直接跳过:
https://192.168.48.130:30001/
-
跳过后出现如下页面
-
创建一个serviceaccount账号
kubectl create serviceaccount dashboard-admin -n kube-system # 名字叫dashboard-admin
-
将创建账号进行权限绑定
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin # dashboard-admin 具有超级管理员的权限
-
这里使用token认证,我们执行命令拿去token
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
-
展示ui
-
转载
转载自:李振良博客