目前生产部署Kubernetes 集群主要有两种方式:
Kubeadm 是一个K8s 部署工具,提供kubeadm init 和kubeadm join,用于快速部署Kubernetes 集群。
官方地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/
从github 下载发行版的二进制包,手动部署每个组件,组成Kubernetes 集群。
Kubernetes发布官网:https://github.com/kubernetes/kubernetes/releases
Kubeadm 降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易可控,推荐使用二进制包部署Kubernetes 集群,虽然手动部署麻烦点,期间可以学习很多工作原理,也利于后期维护。
一台或多台机器,操作系统CentOS7.x-86_x64
硬件配置:2GB 或更多RAM,2 个CPU 或更多CPU,硬盘30GB 或更多
集群中所有机器之间网络互通 免密登录
可以访问外网,需要拉取镜像
禁止swap 分区
序号 | IP | 角色 | 安装组件 |
---|---|---|---|
1 | 192.168.208.128 | Master | etcd、kube-apiserver、kube-controller-manager、kube-scheduler、docker |
2 | 192.168.208.129 | nodes | kubelet,kube-proxy,docker |
3 | 192.168.208.130 | nodes | kubelet,kube-proxy,docker |
软件版本
序号 | 软件名称 | 版本 | 下载地址 |
---|---|---|---|
1 | centos | v7.4.1708 | http://mirrors.163.com/centos/ |
2 | etcd | v3.3.27 | https://github.com/coreos/etcd/releases |
3 | docker | v20.10.12 | http://mirrors.163.com/docker-ce/linux/static/stable/x86_64/ |
4 | kubernetes | v1.23.5 | https://github.com/kubernetes/kubernetes/releases |
5 | cfssl | v1.6.1 | https://github.com/cloudflare/cfssl/releases/ |
#配置所有hosts
cat <> /etc/hosts
192.168.208.128 k8s-master
192.168.208.129 k8s-nodes01
192.168.208.130 k8s-nodes02
EOF
#配置yum源
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
#安装必要依赖
yum install wget vim net-tools telnet lrzsz tree ntpdate ipvsadm ipset sysstat jq psmisc lvm2 git conntrack libseccomp -y
#关闭防火墙firewalld/selinux
systemctl stop firewalld && systemctl disable firewalld
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config && setenforce 0
#关闭swap
swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
#时间同步,按需同步
ntpdate time2.aliyun.com
crontab -e
*/5 * * * * ntpdate time2.aliyun.com
====================================================================
#优化Linux内核
#配置ulimit
ulimit -SHn 65535
cat >> /etc/security/limits.conf < /etc/modules-load.d/ipvs.conf << EFO
ip_vs
ip_vs_lc
ip_vs_wlc
ip_vs_rr
ip_vs_wrr
ip_vs_lblc
ip_vs_lblcr
ip_vs_dh
ip_vs_sh
ip_vs_fo
ip_vs_nq
ip_vs_sed
ip_vs_ftp
ip_vs_sh
nf_conntrack
ip_tables
ip_set
xt_set
ipt_set
ipt_rpfilter
ipt_REJECT
ipip
EFO
systemctl enable --now systemd-modules-load.service
#添加k8s内核参数
cat > /etc/sysctl.d/kubernetes.conf <
参考来源
https://www.cnblogs.com/wdyjx/p/16004407.html
https://blog.csdn.net/jato333/article/details/123956783
https://zhuanlan.zhihu.com/p/472693562
#上传etcd包并解压,配置
#下载cfssl包并赋权
#解压etcd
tar -zxvf etcd-v3.3.27-linux-amd64.tar.gz -C /usr/local/
cd /usr/local/etcd-v3.3.27-linux-amd64/ && cp etcd* /usr/local/bin/
#下载cfssl
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl_1.6.1_linux_amd64
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.1_linux_amd64
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl-certinfo_1.6.1_linux_amd64
#赋权并移动
chmod +x cfssl*
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo
#先创建目录,很重要
mkdir -p /etc/etcd/
mkdir -p /var/lib/etcd/ ;chmod 757 -R /var/lib/etcd/
#根据实际需求修改
cat > /etc/etcd/etcd.conf << EOF
#[Member]
#etcd名称,可自定义
ETCD_NAME="etcd1"
#etcd数据目录,需提前创建好
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
#集群通信监听地址
#ETCD_LISTEN_PEER_URLS="https://192.168.208.128:2380"
#etcd对外监听的IP和端口,默认只监听127.0.0.1,监听全网则需要配置上自己的IP地址,也可以写成0.0.0.0
ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,https://192.168.208.128:2379"
#[Clustering]
#对外宣告集群内部通信端口,若有多台etcd服务器,则需要把这里打开
#ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.208.128:2380"
#etcd对外访问IP地址,填写真实etcd服务器的IP
ETCD_ADVERTISE_CLIENT_URLS="http://127.0.0.1:2379,https://192.168.208.128:2379"
#集群节点地址,若有多台etcd服务器,则需要把这里打开
#ETCD_INITIAL_CLUSTER="etcd1=https://192.168.208.128:2380,etcd2=https://192.168.208.129:2380"
#ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
#ETCD_INITIAL_CLUSTER_STATE="new"
EOF
#需要注意:etcd的配置文件、数据目录、ssl证书目录、启动文件的路径
cat >/usr/lib/systemd/system/etcd.service <
#先创建所需目录
mkdir -p /data/cert/
mkdir -p /etc/etcd/ssl/
cd /data/cert/
生成证书的ca机构
#生成申请文件
cat > ca-csr.json << EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "k8s",
"OU": "system"
}
],
"ca": {
"expiry": "87600h"
}
}
EOF
生成ca证书
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
创建etcd证书的ca
cat > ca-config.json << EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF
#生成etcd证书申请文件
#下列hosts字段中IP为所有etcd节点的集群内部通信ip,一个都不能少,为了方便后期扩容可以多写几个预留的IP
cat > etcd-csr.json << EOF
{
"CN": "etcd",
"hosts": [
"127.0.0.1",
"192.168.208.128",
"192.168.208.129"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "k8s",
"OU": "system"
}]
}
EOF
生成etcd证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
移动证书
cp ca*.pem /etc/etcd/ssl/
cp etcd*.pem /etc/etcd/ssl/
#启动etcd
systemctl enable etcd && systemctl start etcd
#检查状态,多个ip用逗号分割
ETCDCTL_API=3 /usr/local/bin/etcdctl --write-out=table --cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem --endpoints=https://192.168.208.128:2379 endpoint health
#常用命令
./etcdctl --endpoints=ip,ip,ip endpoint status
./etcdctl --endpoints=ip,ip,ip endpoint health
./etcdctl --endpoints=ip,ip,ip endpoint hashkv
./etcdctl --endpoints=ip,ip,ip member list
./etcdctl --endpoints=ip,ip,ip check perf
./etcdctl --endpoints=ip,ip,ip check datascale
声明:如有问题可“tail -fn 50 /var/log/message”来协助查看系统日志进行分析。
#上传kubernetes包并解压,配置
tar -zxvf kubernetes-server-linux-amd64.tar.gz
cd kubernetes/server/bin/
cp kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin
# 拷贝至nodes,这一步是将kubelet、kube-proxy两个组件拷贝至nodes节点
scp kubelet kube-proxy k8s-nodes01:/usr/local/bin/
#创建工作目录
mkdir -p /etc/kubernetes/
mkdir -p /etc/kubernetes/ssl/
mkdir -p /var/log/kubernetes/
#下列hosts字段中IP为所有Master/LB/VIP节点的ip(包括service段ip、pod内部通信ip),一个都不能少,为了方便后期扩容可以多写几个预留的IP。
#由于该证书后续被 kubernetes master 集群使用,需要将master节点的IP都填上,同时还需要填写 service 网络的首个IP。(一般是 kube-apiserver 指定的 service-cluster-ip-range 网段的第一个IP,如 10.255.0.1)
cat > kube-apiserver-csr.json <
签发apiserver证书
#生成证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-apiserver-csr.json | cfssljson -bare kube-apiserver
TLS Bootstraping:Master apiserver启用TLS认证后,Node节点kubelet和kube-proxy要与kube-apiserver进行通信,必须使用CA签发的有效证书才可以,当Node节点很多时,这种客户端证书颁发需要大量工作,同样也会增加集群扩展复杂度。为了简化流程,Kubernetes引入了TLS bootstraping机制来自动颁发客户端证书,kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。所以强烈建议在Node上使用这种方式,目前主要用于kubelet,kube-proxy还是由我们统一颁发一个证书。
#生成token
cat > token.csv << EOF
$(head -c 16 /dev/urandom | od -An -t x | tr -d ' '),kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
##或者也可用下面方式生成
# 格式:token,用户名,UID,用户组
# token也可自行生成替换;
# head -c 16 /dev/urandom | od -An -t x | tr -d ' '
cat > token.csv << EOF
62ce460c38be936045f25d99f8a5aa45,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
移动apiserver证书
\cp ca*.pem /etc/kubernetes/ssl/
\cp kube-apiserver*.pem /etc/kubernetes/ssl/
\cp token.csv /etc/kubernetes/
##根据实际需求修改,需要注意相关配置文件、数据目录、ssl证书目录等路径
cat > /etc/kubernetes/kube-apiserver.conf << EOF
KUBE_APISERVER_OPTS="--anonymous-auth=false \\
--bind-address=192.168.208.128 \\
--secure-port=6443 \\
--advertise-address=192.168.208.128 \\
--insecure-port=0 \\
--authorization-mode=RBAC,Node \\
--runtime-config=api/all=true \\
--enable-bootstrap-token-auth=true \\
--service-cluster-ip-range=10.255.0.0/16 \\
--token-auth-file=/etc/kubernetes/token.csv \\
--service-node-port-range=30000-50000 \\
--tls-cert-file=/etc/kubernetes/ssl/kube-apiserver.pem \\
--tls-private-key-file=/etc/kubernetes/ssl/kube-apiserver-key.pem \\
--client-ca-file=/etc/kubernetes/ssl/ca.pem \\
--kubelet-client-certificate=/etc/kubernetes/ssl/kube-apiserver.pem \\
--kubelet-client-key=/etc/kubernetes/ssl/kube-apiserver-key.pem \\
--service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \\
--service-account-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \\
--service-account-issuer=https://kubernetes.default.svc.cluster.local \\
--etcd-cafile=/etc/etcd/ssl/ca.pem \\
--etcd-certfile=/etc/etcd/ssl/etcd.pem \\
--etcd-keyfile=/etc/etcd/ssl/etcd-key.pem \\
--etcd-servers=https://192.168.208.128:2379,https://192.168.208.129:2379 \\
--enable-swagger-ui=true \\
--allow-privileged=true \\
--enable-admission-plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\
--apiserver-count=3 \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/var/log/kube-apiserver-audit.log \\
--event-ttl=1h \\
--alsologtostderr=true \\
--logtostderr=false \\
--log-dir=/var/log/kubernetes \\
--v=4"
EOF
##===参数说明
–logtostderr:启用日志
–v:日志等级
–log-dir:日志目录
–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:bootstrap token文件
–service-node-port-range:Service nodeport类型默认分配端口范围
–kubelet-client-xxx:apiserver访问kubelet客户端证书
–tls-xxx-file:apiserver https证书
–etcd-xxxfile:连接Etcd集群证书
–audit-log-xxx:审计日志
#需要注意:apiserver的配置文件、数据目录、ssl证书目录、启动文件的路径
cat > /usr/lib/systemd/system/kube-apiserver.service <
systemctl daemon-reload
systemctl start kube-apiserver && systemctl enable kube-apiserver
声明:如有问题可“tail -fn 50 /var/log/messages”来协助查看系统日志进行分析。
#生成证书申请文件
# hosts 列表包含所有 kube-controller-manager 节点 IP;
# CN 为 system:kube-controller-manager
# O 为 system:kube-controller-manager,kubernetes 内置的 ClusterRoleBindings system:kube-controller-manager 赋予 kube-controller-manager 工作所需的权限
cat > kube-controller-manager-csr.json <<-EOF
{
"CN": "system:kube-controller-manager",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
"127.0.0.1",
"192.168.208.128",
"192.168.208.129"
],
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "system:kube-controller-manager",
"OU": "system"
}
]
}
EOF
签发controller-manager证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
cp kube-controller-manager*.pem /etc/kubernetes/ssl/
cp kube-controller-manager.kubeconfig /etc/kubernetes/
#设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://192.168.208.128:6443 \
--kubeconfig=kube-controller-manager.kubeconfig
#设置客户端认证参数
kubectl config set-credentials system:kube-controller-manager \
--client-certificate=kube-controller-manager.pem \
--client-key=kube-controller-manager-key.pem \
--embed-certs=true \
--kubeconfig=kube-controller-manager.kubeconfig
#设置上下文参数
kubectl config set-context system:kube-controller-manager \
--cluster=kubernetes \
--user=system:kube-controller-manager \
--kubeconfig=kube-controller-manager.kubeconfig
#设置默认上下文
kubectl config use-context system:kube-controller-manager \
--kubeconfig=kube-controller-manager.kubeconfig
##根据实际需求修改,需要注意相关配置文件、数据目录、ssl证书目录等路径
cat > /etc/kubernetes/kube-controller-manager.conf << EOF
KUBE_CONTROLLER_MANAGER_OPTS=" \\
--bind-address=127.0.0.1 \\
--kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \\
--service-cluster-ip-range=10.255.0.0/16 \\
--cluster-name=kubernetes \\
--cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \\
--cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \\
--allocate-node-cidrs=true \\
--cluster-cidr=10.186.0.0/16 \\
--experimental-cluster-signing-duration=87600h \\
--root-ca-file=/etc/kubernetes/ssl/ca.pem \\
--service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \\
--leader-elect=true \\
--tls-cert-file=/etc/kubernetes/ssl/kube-controller-manager.pem \\
--tls-private-key-file=/etc/kubernetes/ssl/kube-controller-manager-key.pem \\
--logtostderr=false \\
--log-dir=/var/log/kubernetes \\
--v=4"
EOF
#需要注意:controller-manager配置文件、数据目录、ssl证书目录、启动文件的路径
cat > /usr/lib/systemd/system/kube-controller-manager.service << EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/etc/kubernetes/kube-controller-manager.conf
ExecStart=/usr/local/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable kube-controller-manager && systemctl start kube-controller-manager
声明:如有问题可“tail -fn 50 /var/log/messages”来协助查看系统日志进行分析。
# hosts 列表包含所有 kube-scheduler 节点 IP;
# CN 为 system:kube-scheduler
# O 为 system:kube-scheduler,kubernetes 内置的 ClusterRoleBindings system:kube-scheduler 将赋予 kube-scheduler 工作所需的权限。
cat > kube-scheduler-csr.json << EOF
{
"CN": "system:kube-scheduler",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
"127.0.0.1",
"192.168.208.128",
"192.168.208.129"
],
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "system:kube-scheduler",
"OU": "system"
}
]
}
EOF
签发scheduler证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler
cp kube-scheduler*.pem /etc/kubernetes/ssl/
cp kube-scheduler.kubeconfig /etc/kubernetes/
#设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://192.168.208.128:6443 \
--kubeconfig=kube-scheduler.kubeconfig
#设置客户端认证参数
kubectl config set-credentials system:kube-scheduler \
--client-certificate=kube-scheduler.pem \
--client-key=kube-scheduler-key.pem \
--embed-certs=true \
--kubeconfig=kube-scheduler.kubeconfig
#设置上下文参数
kubectl config set-context system:kube-scheduler \
--cluster=kubernetes \
--user=system:kube-scheduler \
--kubeconfig=kube-scheduler.kubeconfig
#设置默认上下文
kubectl config use-context system:kube-scheduler \
--kubeconfig=kube-scheduler.kubeconfig
##根据实际需求修改,需要注意相关配置文件、数据目录等路径
cat > /etc/kubernetes/kube-scheduler.conf << EOF
KUBE_SCHEDULER_OPTS="--address=127.0.0.1 \\
--kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \\
--leader-elect=true \\
--alsologtostderr=true \\
--logtostderr=false \\
--log-dir=/var/log/kubernetes \\
--v=4"
EOF
cat > /usr/lib/systemd/system/kube-scheduler.service << EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/etc/kubernetes/kube-scheduler.conf
ExecStart=/usr/local/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable kube-scheduler && systemctl start kube-scheduler
声明:如有问题可“tail -fn 50 /var/log/messages”来协助查看系统日志进行分析。
至此,Master节点上的三个组件(Apiserver、ControllerManager、Scheduler)已部署并启动成功,下面来检查一下所有组件的状态吧。
## 这里也可以认为是 部署kubectl组件。
cat > admin-csr.json << EOF
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "system:masters",
"OU": "system"
}
]
}
EOF
说明:
后续 kube-apiserver 使用 RBAC 对客户端(如 kubelet、kube-proxy、Pod)请求进行授权;
kube-apiserver 预定义了一些 RBAC 使用的 RoleBindings,如 cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 的所有 API的权限;
O指定该证书的 Group 为 system:masters,kubelet 使用该证书访问 kube-apiserver 时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的 system:masters,所以被授予访问所有 API 的权限;
注:
这个admin 证书,是将来生成管理员用的kube config 配置文件用的,现在我们一般建议使用RBAC 来对kubernetes 进行角色权限控制, kubernetes 将证书中的CN 字段 作为User, O 字段作为 Group;
“O”: “system:masters”, 必须是system:masters,否则后面kubectl create clusterrolebinding报错。
签发证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
移动证书
cp admin*.pem /etc/kubernetes/ssl/
mkdir ~/.kube
cp kube.config ~/.kube/config
# kubeconfig 为 kubectl 的配置文件,包含访问 apiserver 的所有信息,如 apiserver 地址、CA 证书和自身使用的证书
#设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://192.168.208.128:6443 \
--kubeconfig=kube.config
#设置客户端认证参数
kubectl config set-credentials admin \
--client-certificate=admin.pem \
--client-key=admin-key.pem \
--embed-certs=true \
--kubeconfig=kube.config
#设置上下文参数
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=admin \
--kubeconfig=kube.config
#设置默认上下文
kubectl config use-context kubernetes \
--kubeconfig=kube.config
# mkdir ~/.kube
# cp kube.config ~/.kube/config
#授权kubernetes证书访问kubelet api权限
#即授权用户允许请求证书
kubectl create clusterrolebinding kube-apiserver:kubelet-apis \
--clusterrole=system:kubelet-api-admin \
--user kubernetes
上面步骤完成后,kubectl就可以与kube-apiserver通信了。
kubectl get cs
kubectl cluster-info
kubectl get componentstatuses
kubectl get all --all-namespaces
#上传docker包并解压,配置
tar -zxvf docker-20.10.12.tgz
cp docker/* /usr/local/bin/
## 创建/etc/docker目录,配置daemon.json文件
mkdir -p /etc/docker/
tee /etc/docker/daemon.json <<-EOF
{
"registry-mirrors": ["https://u7vs31xg.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
cat > /usr/lib/systemd/system/docker.service << EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/local/bin/dockerd
ExecReload=/bin/kill -s HUP
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 enable docker && systemctl restart docker
#创建工作目录
mkdir -p /etc/kubernetes/
mkdir -p /etc/kubernetes/ssl/
mkdir -p /etc/kubernetes/manifests/
mkdir -p /var/log/kubernetes/
mkdir -p /var/lib/kubelet
此步骤需在Master节点上执行!
#创建node必备,不然node节点上的kubelet无法启动,就是创建一个可以申请证书的用户
BOOTSTRAP_TOKEN=$(awk -F "," '{print $1}' /etc/kubernetes/token.csv)
#设置集群参数
kubectl config set-cluster kubernetes --certificate-authority=ca.pem --embed-certs=true --server=https://192.168.208.128:6443 --kubeconfig=kubelet-bootstrap.kubeconfig
#设置客户端认证参数
kubectl config set-credentials kubelet-bootstrap --token=${BOOTSTRAP_TOKEN} --kubeconfig=kubelet-bootstrap.kubeconfig
#设置上下文参数
kubectl config set-context default --cluster=kubernetes --user=kubelet-bootstrap --kubeconfig=kubelet-bootstrap.kubeconfig
#设置默认上下文
kubectl config use-context default --kubeconfig=kubelet-bootstrap.kubeconfig
#创建角色绑定
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
Nodes节点执行。
cat > /etc/kubernetes/kubelet-config.yml << EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 0.0.0.0
port: 10250
readOnlyPort: 10255
cgroupDriver: systemd
clusterDNS:
- 10.255.0.2
clusterDomain: cluster.local
failSwapOn: false
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 2m0s
enabled: true
x509:
clientCAFile: /etc/kubernetes/ssl/ca.pem
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 5m0s
cacheUnauthorizedTTL: 30s
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
maxOpenFiles: 1000000
maxPods: 110
EOF
# kubelet-config.yml配置文件[address]参数改为各个node节点的ip地址,也可以是0.0.0.0
# 如果docker的驱动为systemd,[cgroupDriver]参数处修改为systemd,此处设置很重要,否则后面node节点无法加入到集群
cat > /usr/lib/systemd/system/kubelet.service << EOF
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/usr/local/bin/kubelet \\
--hostname-override=k8s-nodes01 \\
--bootstrap-kubeconfig=/etc/kubernetes/kubelet-bootstrap.kubeconfig \\
--kubeconfig=/etc/kubernetes/kubelet.kubeconfig \\
--config=/etc/kubernetes/kubelet-config.yml \\
--network-plugin=cni \\
--cert-dir=/etc/kubernetes/ssl \\
--pod-infra-container-image=k8s.gcr.io/pause:3.2 \\
--v=4
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
注意:–pod-infra-container-image:管理Pod网络容器的镜像。
k8s.gcr.io/pause:3.2镜像默认无法直接下载,需通过阿里云镜像仓库下载;也可指定自己的私有仓库地址。
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 k8s.gcr.io/pause:3.2
docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2
#pull coredns组件
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.7.0
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.7.0 k8s.gcr.io/coredns:1.7.0
docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.7.0
#Nodes节点执行
#将Master节点上的证书拷贝到node
cd /etc/kubernetes/
scp -rp k8s-master:/data/cert/kubelet-bootstrap.kubeconfig ./
scp -rp k8s-master:/data/cert/ca.pem ./ssl/
scp -rp k8s-master:/data/cert/ca-key.pem ./ssl/
systemctl daemon-reload && systemctl enable kubelet
systemctl start kubelet && systemctl status kubelet
确认kubelet服务启动成功后,接着到Master节点上Approve一下bootstrap请求。执行如下命令可以看到Nodes节点发送的 CSR 请求:
kubectl get csr
#批准kubelet证书申请并加入集群
kubectl certificate approve <查询到的请求名称>
#例如:
kubectl certificate approve node-csr-O73Wkk6YcpWMOb0Tmyt_AN2zxn1U5qqc6wlWufIL9Zo
kubectl get csr
#删除csr可执行
kubectl delete csr node-csr-O73Wkk6YcpWMOb0Tmyt_AN2zxn1U5qqc6wlWufIL9Zo
#此时也可查看nodes
kubectl get nodes
node节点验证
在node节点ssl目录可以看到,多了2个kubelet的证书文件。
cat > kube-proxy-csr.json << EOF
{
"CN": "system:kube-proxy",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "k8s",
"OU": "system"
}]
}
EOF
签发proxy证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
生成kubeconfig文件
#设置集群参数
kubectl config set-cluster kubernetes --certificate-authority=ca.pem --embed-certs=true --server=https://192.168.208.128:6443 --kubeconfig=kube-proxy.kubeconfig
#设置客户端认证参数
kubectl config set-credentials kube-proxy --client-certificate=kube-proxy.pem --client-key=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
#nodes 节点操作
#将Master节点上的证书拷贝到node
mkdir -p /var/lib/kube-proxy
cd /etc/kubernetes/
scp -rp k8s-master:/data/cert/kube-proxy.kubeconfig ./
scp -rp k8s-master:/data/cert/kube-proxy.pem ./ssl/
scp -rp k8s-master:/data/cert/kube-proxy-key.pem ./ssl/
Nodes节点上执行。
#node01节点操作
#clusterCIDR 此处网段必须与网络组件网段保持一致,否则部署网络组件时会报错
cat > /etc/kubernetes/kube-proxy.yaml << EOF
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 192.168.208.129
clientConnection:
kubeconfig: /etc/kubernetes/kube-proxy.kubeconfig
clusterCIDR: 10.186.0.0/16
healthzBindAddress: 192.168.208.129:10256
kind: KubeProxyConfiguration
metricsBindAddress: 192.168.208.129:10249
mode: "ipvs"
EOF
cat > /usr/lib/systemd/system/kube-proxy.service << EOF
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
WorkingDirectory=/var/lib/kube-proxy
ExecStart=/usr/local/bin/kube-proxy \\
--config=/etc/kubernetes/kube-proxy.yaml \\
--alsologtostderr=true \\
--logtostderr=false \\
--log-dir=/var/log/kubernetes \\
--v=4
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl restart kube-proxy && systemctl enable kube-proxy
Master节点安装。
# 获取calico
wget https://docs.projectcalico.org/v3.14/manifests/calico.yaml
# 执行安装操作
kubectl apply -f calico.yaml
#或者可直接线上安装
#kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
# 查看pod
kubectl get pods -A
# 查看node节点
kubectl get nodes
Master节点安装。
#获取coredns文件
wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/coredns/coredns.yaml.base
#重命名
cp coredns.yaml.base coredns.yaml
>>>
修改yaml文件,有4处修改:
kubernetes cluster.local in-addr.arpa ip6.arpa
forward . /etc/resolv.conf
memory: 170Mi
clusterIP为:10.255.0.2(kubelet配置文件中的clusterDNS)
>>>
#安装
kubectl apply -f coredns.yaml
Dashboard 版本需要与 K8S 版本相匹配,参考:https://github.com/kubernetes/dashboard/releases
#获取文件
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml
>>>
# 修改kubernetes-dashboard的Service类型
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort # 新增
ports:
- port: 443
targetPort: 8443
nodePort: 30009 # 新增
selector:
k8s-app: kubernetes-dashboard
>>>
#创建
kubectl create -f recommended.yaml
#创建管理员用户
kubectl apply -f admin.yaml -n kube-system
同Nodes01节点!!!
使用sealos工具安装kubernetes集群
sealos 是基于go的k8s安装工具,能帮助用户快速构建一套高可用集群,支持如下特性:
- 独立的应用镜像封装,开箱即用;
- 支持离线安装,安装速度快;
- 证书100年有效期;
- 集群扩容方便;
下载离线包:
链接:https://pan.baidu.com/s/1w3kRN9hgCXV-oKQxQASA9g?pwd=fmmo
提取码:fmmo
官网 :https://www.sealyun.com/zh-Hans/docs/getting-started/installation:
高版本离线包自带docker/containerd
,如没安装docker/containerd
会自动安装.
k8s1.22
版本及以上
强制安装containerd
,要求卸载docker
.
IP | 系统 | 角色 | 主机名 |
---|---|---|---|
192.168.80.7 | CentOS7.6 | master | k8s-master-1 |
192.168.80.17 | CentOS7.6 | node | k8s-master-2 |
192.168.80.27 | CentOS7.6 | node | k8s-master-3 |
192.168.80.37 | CentOS7.6 | node | k8s-node-1 |
按主机规划设备各主机的主机名,并在 /etc/hosts 文件中添加解析配置
#修改主机名
hostnamectl set-hostname k8s-master-1
#修改/etc/hosts,添加以下配置
vim /etc/hosts
192.168.80.7 k8s-master-1
192.168.80.17 k8s-master-2
192.168.80.27 k8s-master-3
192.168.80.37 k8s-node-1
# 停止
systemctl stop firewalld.service
# 禁用
systemctl disable firewalld.service
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
swapoff -a
# 设置时区
timedatectl set-timezone Asia/Shanghai
# 同步时间
yum install -y ntpdate
ntpdate time1.aliyun.com
在命令窗口中输入:
ssh-keygen
然后连续回车即可,出现如下界面就ok:
复制公钥到其他节点
ssh-copy-id -i .ssh/id_rsa.pub [email protected] #复制密钥
ssh-copy-id -i .ssh/id_rsa.pub [email protected] #复制密钥
复制完成即可实现免密登录,测试一下:
ssh 192.168.35.102 #直接登录
如果成功登录到192.168.35.102这台服务器,说明你的免密登录配置成功。
设置本机免密:
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
(1) 下载并安装sealos,sealos是个golang的二进制工具,直接下载拷贝到bin目录即可, release页面也可下载,当时latest版本为v3.3.9,目前最新版本为v4.1.6,安装k8s集群的方式已不同,请参考官网,v3.3.9-rc11下载地址为:https://github.com/labring/sealos/releases/download/v3.3.9-rc.11/sealos_3.3.9-rc.11_linux_amd64.tar.gz
wget -c https://sealyun.oss-cn-beijing.aliyuncs.com/latest/sealos && chmod +x sealos && mv sealos /usr/bin
(2) 下载离线资源包(请自行下载)
#新建软件包存放目录
mkdir -pv /usr/local/soft/package
#下载软件包
kube1.18.14.tar.gz
(3) 安装集群
sealos init --passwd '123456' \
--master 192.168.80.7 --master 192.168.80.17 --master 192.168.80.27 \
--node 192.168.80.37 \
--pkg-url /usr/local/soft/package/kube1.18.14.tar.gz \
--version v1.18.14
# v1.22.0也可以
参数含义
参数名 | 含义 | 示例 | 是否必须 |
---|---|---|---|
passwd | 服务器密码 | 123456 | 和私钥二选一 |
master | k8s master节点IP地址 | 192.168.0.2 | 必须 |
node | k8s node节点IP地址 | 192.168.80.37 | 可选 |
pkg-url | 离线资源包地址,支持下载到本地,或者一个远程地址 | /root/kube1.16.0.tar.gz | 必须 |
version | 资源包对应的版本 | v1.18.14 | 必须 |
kubeadm-config | 自定义kubeadm配置文件 | kubeadm.yaml.temp | 可选 |
pk | ssh私钥地址,免密钥时使用 | /root/.ssh/id_rsa | 和passwd二选一 |
pk-passwd | ssh私钥密码 | 默认为空 | 私钥有密码时添加即可 |
user | ssh用户名 | root | 可选 |
interface | 机器网卡名,CNI网卡发现用 | eth.* | 可选 |
network | CNI类型如calico flannel | calico | 可选 |
podcidr | pod网段 | 100.64.0.0/10 | 可选 |
repo | 镜像仓库,离线包通常不用配置,除非你把镜像导入到自己私有仓库了 | k8s.gcr.io | 可选 |
svccidr | clusterip网段 | 10.96.0.0/12 | 可选 |
vlog | kubeadm 日志等级 | 5 | 可选 |
cert-sans | kubernetes apiServerCertSANs | sealyun.com | 可选 |
without-cni | 不装cni插件,为了用户自己装别的CNI | 默认安装calico-cni | 可选 |
(4) 等待安装完成即可
(5) 其它命令
#增加master
sealos join --master 192.168.80.47 --master 192.168.80.57
sealos join --master 192.168.80.47-192.168.80.57 # 或者多个连续IP
#增加node
sealos join --node 192.168.80.47 --master 192.168.80.57
sealos join --node 192.168.80.47-192.168.80.57 # 或者多个连续IP
#删除指定master节点
sealos clean --master 192.168.80.47 --master 192.168.80.57
sealos clean --master 192.168.80.47-192.168.80.57 # 或者多个连续IP
#删除指定node节点
sealos clean --node 192.168.80.47 --node 192.168.80.57
sealos clean --node 192.168.80.47-192.168.80.57 # 或者多个连续IP
#清理集群
sealos clean --all
#备份集群
sealos etcd save
(1) 下载并安装sealos,sealos是个golang的二进制工具,直接下载拷贝到bin目录即可, release页面也可下载
wget -c https://sealyun.oss-cn-beijing.aliyuncs.com/latest/sealos && chmod +x sealos && mv sealos /usr/bin
(2) 下载离线资源包(请自行下载)
#新建软件包存放目录
mkdir -pv /usr/local/soft/package
#下载软件包
kube1.18.14.tar.gz
(3) 安装集群
sealos init --passwd '123456' \
--master 192.168.80.7 --master 192.168.80.17 --master 192.168.80.27 \
--node 192.168.80.37 \
--without-cni \
--pkg-url /usr/local/soft/package/kube1.18.14.tar.gz \
--version v1.18.14
#使用flannel网络插件时,可以添加 --podcidr 10.244.0.0/16 参数,后续就不用改kube-flannel.yml文件中的网段,而直接使用 kubectl apply -f kube-flannel.yml 即可
(4) 下载cni网络插件工具
#下载
wget -c https://github.com/containernetworking/plugins/releases/download/v0.9.1/cni-plugins-linux-amd64-v0.9.1.tgz
#创建目录
mkdir -pv /opt/cni/bin
#解压
tar -xf cni-plugins-linux-amd64-v0.9.1.tgz -C /opt/cni/bin/
(5) 安装flannel插件
wget -c https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
#修改kube-flannel.yml文件中的网段,如果和pod的网段不在同一网段,在pod内可能ping不通外网
vim kube-flannel.yml
#找到以下内容,将Network的值改为100.64.0.0/10,sealos默认安装的podcidr为100.64.0.0/24
net-conf.json: |
{
"Network": "10.244.0.0/16", #修改此处
"Backend": {
"Type": "vxlan"
}
}
kubectl apply -f kube-flannel.yml
kube-flannel.yml 文件内容如下:
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp.flannel.unprivileged
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default
seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
spec:
privileged: false
volumes:
- configMap
- secret
- emptyDir
- hostPath
allowedHostPaths:
- pathPrefix: "/etc/cni/net.d"
- pathPrefix: "/etc/kube-flannel"
- pathPrefix: "/run/flannel"
readOnlyRootFilesystem: false
# Users and groups
runAsUser:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
fsGroup:
rule: RunAsAny
# Privilege Escalation
allowPrivilegeEscalation: false
defaultAllowPrivilegeEscalation: false
# Capabilities
allowedCapabilities: ['NET_ADMIN', 'NET_RAW']
defaultAddCapabilities: []
requiredDropCapabilities: []
# Host namespaces
hostPID: false
hostIPC: false
hostNetwork: true
hostPorts:
- min: 0
max: 65535
# SELinux
seLinux:
# SELinux is unused in CaaSP
rule: 'RunAsAny'
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: flannel
rules:
- apiGroups: ['extensions']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames: ['psp.flannel.unprivileged']
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- ""
resources:
- nodes
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: flannel
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flannel
subjects:
- kind: ServiceAccount
name: flannel
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: flannel
namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
name: kube-flannel-cfg
namespace: kube-system
labels:
tier: node
app: flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "100.64.0.0/10",
"Backend": {
"Type": "vxlan"
}
}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel-ds
namespace: kube-system
labels:
tier: node
app: flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
tier: node
app: flannel
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
hostNetwork: true
priorityClassName: system-node-critical
tolerations:
- operator: Exists
effect: NoSchedule
serviceAccountName: flannel
initContainers:
- name: install-cni
image: quay.io/coreos/flannel:v0.14.0
command:
- cp
args:
- -f
- /etc/kube-flannel/cni-conf.json
- /etc/cni/net.d/10-flannel.conflist
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
mountPath: /etc/kube-flannel/
containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.14.0
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
resources:
requests:
cpu: "100m"
memory: "50Mi"
limits:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: false
capabilities:
add: ["NET_ADMIN", "NET_RAW"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: run
mountPath: /run/flannel
- name: flannel-cfg
mountPath: /etc/kube-flannel/
volumes:
- name: run
hostPath:
path: /run/flannel
- name: cni
hostPath:
path: /etc/cni/net.d
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
(6) 下载并导入镜像
因国内网络原因,quay.io镜像可能拉取不到,可以用中科大镜像,然后修改tag即可,如果是内网,建议在有网的主机上下载,然后上传导入。
#拉取镜像
docker pull quay.mirrors.ustc.edu.cn/coreos/flannel:v0.14.0
#打标签
docker tag quay.mirrors.ustc.edu.cn/coreos/flannel:v0.14.0 quay.io/coreos/flannel:v0.14.0
#导出
docker save quay.io/coreos/flannel:v0.14.0 | gzip > flannel-014.tgz
#导入
docker load -i flannel-014.tgz
sealos默认使用的calico插件,有些云平台可能不支持,导致主节点上的NodePort无法telnet,也无法访问。有可能需要更换网络插件为flannel。
(1) 清空iptables规则
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
(2) 停用tunl0虚拟网卡
ip link set tunl0 down
(3) 删除calico的一些文件
rm -f /etc/cni/net.d/*
rm -rf /run/calico/
(4) 替换cni网络插件工具
#下载
wget -c https://github.com/containernetworking/plugins/releases/download/v0.9.1/cni-plugins-linux-amd64-v0.9.1.tgz
#备份
mkdir /root/cni-bak
mv /opt/cni/bin/* cni-bak/
#解压
tar -xf cni-plugins-linux-amd64-v0.9.1.tgz -C /opt/cni/bin/
(5) 安装flannel插件
wget -c https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml
(6) 重启docker和kubelet
systemctl restart docker
systemctl restart kubelet
(7) 修改iptables FORWARD 链中访问规则(如有需要)
iptables -P FORWARD ACCEPT
#或开启内核数据包转发参数
net.ipv4.ip_forward = 1
安装后操作命令说明:操作镜像获容器使用nerdctl 而不docker
nerdctl 是用于containerd 并且兼容docker cli 习惯的管理工具,主要适用于刚从 docker 转到 containerd 的用户,操作 containerd 的命令行工具 ctr 和crictl 不怎么好用,所以就有了
master节点参与调度的设置方法
默认情况下,master节点是不参与调度的,且在master节点上有一个污点NoSchedule(表示k8s将不会将Pod调度到具有该污点的Node上),如果想让master节点参与调度,需要先删除污点,允许k8s将Pod调度到该Node上,再添加master为nodes角色。
假设我们就一台单机环境,想让k8s平台既是master节点、又是node节点,可通过如下步骤实现:
删除污点
# 查看node
kubectl get nodes
# 查看污点
kubectl describe node k8s-master |grep Taints
Taints: node-role.kubernetes.io/master:NoSchedule
# 删除污点
kubectl taint nodes --all node-role.kubernetes.io/master-
添加master为worker角色
语法:kubectl label nodes 节点名字 node-role.kubernetes.io/ROLES属性名称=或-
# 让master节点参与调度,#如果想删除,把=换成-
kubectl label nodes k8s-master node-role.kubernetes.io/worker=
也可以将control-plane标签删除。
kubectl label nodes k8s-master node-role.kubernetes.io/control-plane-
配置kubectl命令补全
离线方式
#下载离线包,下载地址:
https://github.com/scop/bash-completion/releases
#解压
tar -xvJf bash-completion-2.11.tar.xz
#命令补全生效
cd bash-completion-2.11
source $PWD/bash_completion
#当前用户生效
echo 'source <(kubectl completion bash)' >>~/.bashrc
source ~/.bashrc
# 全局生效
kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null
或
echo 'source <(kubectl completion bash)' >>/etc/profile
sorce /etc/profile
yum方式
#安装bash-completion
yum install bash-completion -y
#执行bash_completion
source /usr/share/bash-completion/bash_completion
#加载kubectl completion
source <(kubectl completion bash)
#
echo "source <(kubectl completion bash)" >> ~/.bashrc
sealos init --master 192.168.0.2 \
--master 192.168.0.3 \
--master 192.168.0.4 \
--node 192.168.0.5 \
--user root \
--passwd your-server-password \
--version v1.14.1 \
--pkg-url /root/kube1.14.1.tar.gz
使用免密钥或者密钥对:
sealos init --master 172.16.198.83 \
--node 172.16.198.84 \
--pkg-url https://sealyun.oss-cn-beijing.aliyuncs.com/free/kube1.15.0.tar.gz \
--pk /root/kubernetes.pem # this is your ssh private key file \
--version v1.15.0
参数解释:
--master master服务器地址列表
--node node服务器地址列表
--user 服务器ssh用户名
--passwd 服务器ssh用户密码
--pkg-url 离线包位置,可以放在本地目录,也可以放在一个 http 服务器上,sealos 会 wget 到安装目标机
--version kubernetes 版本
--pk ssh 私钥地址,配置免密钥默认就是 /root/.ssh/id_rsa
其他参数:
--kubeadm-config string kubeadm-config.yaml kubeadm 配置文件,可自定义 kubeadm 配置文件
--vip string virtual ip (default "10.103.97.2") 本地负载时虚拟 ip,不推荐修改,集群外不可访问
单 master 多 node:
sealos init --master 192.168.0.2 \
--node 192.168.0.5 \
--user root \
--passwd your-server-password \
--version v1.14.1 \
--pkg-url /root/kube1.14.1.tar.gz
先获取 join command,在 master 上执行:
kubeadm token create --print-join-command
可以使用超级 kubeadm,但是 join 时需要增加一个 --master
参数:
cd kube/shell && init.sh
echo "10.103.97.2 apiserver.cluster.local" >> /etc/hosts # using vip
kubeadm join 10.103.97.2:6443 --token 9vr73a.a8uxyaju799qwdjv \
--master 10.103.97.100:6443 \
--master 10.103.97.101:6443 \
--master 10.103.97.102:6443 \
--discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
也可以用 sealos join 命令:
sealos join --master 192.168.0.2 \
--master 192.168.0.3 \
--master 192.168.0.4 \
--vip 10.103.97.2 \
--node 192.168.0.5 \
--user root \
--passwd your-server-password \
--pkg-url /root/kube1.15.0.tar.gz
有时你可能需要自定义 kubeadm 的配置文件,比如要在证书里加入域名 sealyun.com
。
首先需要获取配置文件模板:
sealos config -t kubeadm >> kubeadm-config.yaml.tmpl
然后修改 kubeadm-config.yaml.tmpl
即可,将 sealyun.com
添加到配置中:
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: {{.Version}}
controlPlaneEndpoint: "apiserver.cluster.local:6443"
networking:
podSubnet: 100.64.0.0/10
apiServer:
certSANs:
- sealyun.com # 这是新增的域名
- 127.0.0.1
- apiserver.cluster.local
{{range .Masters -}}
- {{.}}
{{end -}}
- {{.VIP}}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
excludeCIDRs:
- "{{.VIP}}/32"
注意:其它部分不用修改,sealos 会自动填充模板里面的内容。
最后在部署时使用 --kubeadm-config
指定配置文件模板即可:
sealos init --kubeadm-config kubeadm-config.yaml.tmpl \
--master 192.168.0.2 \
--master 192.168.0.3 \
--master 192.168.0.4 \
--node 192.168.0.5 \
--user root \
--passwd your-server-password \
--version v1.14.1 \
--pkg-url /root/kube1.14.1.tar.gz
升级 kubeadm,所有节点导入镜像
升级控制节点
升级 master(控制节点)上的 kubelet
升级其它 master(控制节点)
升级 node
验证集群状态
kubeadm upgrade plan
kubeadm upgrade apply v1.15.0
重启 kubelet:
systemctl restart kubelet
其实 kubelet 升级很简单粗暴,我们只需要把新版本的 kubelet 拷贝到 /usr/bin 下面,重启 kubelet service 即可,如果程序正在使用不让覆盖那么就停一下 kubelet 再进行拷贝,kubelet bin 文件在 conf/bin 目录下。
升级其它控制节点
kubeadm upgrade apply
驱逐节点(要不要驱逐看情况, 喜欢粗暴的直接来也没啥):
$ kubectl drain $NODE --ignore-daemonsets
更新 kubelet 配置:
$ kubeadm upgrade node config --kubelet-version v1.15.0
然后升级 kubelet。同样是替换二进制再重启 kubelet service。
$ systemctl restart kubelet
$ kubectl uncordon $NODE
kubectl get nodes
如果版本信息都对的话基本就升级成功了。
kubeadm upgrade apply 干了啥?
检查集群是否可升级
执行版本升级策略 哪些版本之间可以升级
确认镜像是否存在
执行控制组件升级,如果失败就回滚,其实就是 apiserver、controller manager、scheduler 等这些容器
升级 kube-dns 和 kube-proxy
创建新的证书文件,备份老的如果其超过 180 天
$ sealos clean \
--master 192.168.0.2 \
--master 192.168.0.3 \
--master 192.168.0.4 \
--node 192.168.0.5 \
--user root \
--passwd your-server-password
常用命令
sealos reset:清理集群
sealos add:增加节点
sealos delete:删除节点
sealos save:保存离线镜像包
sealos load:加载离线镜像包
!升级前注意事项:
# 确保集群是健康状态
kubectl get nodes -owid
# 确保kube-system下的pod运行正常
kubectl get pod -n kube-system -owide
执行升级
版本必须要大于等于1.18.0,才可升级
执行升级前提前下载好新版本的离线安装包
# 升级到1.19.2版本
sealos upgrade --version v1.19.2 --pkg-url /root/kube1.19.2.tar.gz -f | tee -a upgrade.1183-1192.log
本地备份, 默认保存在/opt/sealos/ectd-backup
这个目录, 默认名称为sanpshot
# 本地备份etcd数据
sealos etcd save
本地备份
并复制到各master节点
。增加--docker
参数, 默认在生成的文件下添加当前的uinx时间戳
,然后复制到各master节点
.
# 在所有的master节点上备份数据
sealos etcd save --docker
备份上传至oss,首次执行带命令行或者编辑~/.sealos/config.yaml
# 备份上传到阿里云oss
## 需要自行指定oss的ak参数
sealos etcd save --docker \
--aliId youraliyunkeyid \
--aliKey youraliyunkeysecrets \
--ep oss-cn-hangzhou.aliyuncs.com \
--bucket etcdbackup \
--objectPath /sealos/
# 注意clean不加任何参数会清理整个集群,等同于sealos clean --all
sealos clean --all
# 删除指定master节点
sealos clean --master 192.168.0.6 --master 192.168.0.7
sealos clean --master 192.168.0.6-192.168.0.9 # 或者多个连续IP
# 删除指定node节点
sealos clean --node 192.168.0.6 --node 192.168.0.7
sealos clean --node 192.168.0.6-192.168.0.9 # 或者多个连续IP
# 增加master机器
sealos join --master 192.168.0.6 --master 192.168.0.7
sealos join --master 192.168.0.6-192.168.0.9 # 或者多个连续IP
# 增加node机器
sealos join --node 192.168.0.6 --node 192.168.0.7
sealos join --node 192.168.0.6-192.168.0.9 # 或者多个连续IP
pod`的ip地址段,也称为`cidr
# podcidr 参数指定自定义pod网段 如
--podcidr 10.244.0.0/16 \
# svccidr 参数指定clusterip网段 如
--svccidr 10.93.0.0/12 \
# 不安装cni插件
## without-cni sealos自带calico网络,如果你想自己装CNI不用默认可加此参数, 如
sealos init --without-cni …
# 自定义cni插件
-- network flannel
需要添加证书, 在init的时候指定--cert-sans 域名
即可
证书有效期是99年
# 安装k8s集群时添加证书
sealos init --cert-sans 域名 \
--master 192.168.0.2 \
--node 192.168.0.12 \
--pkg-url /root/kube1.22.0.tar.gz \
--version v1.22.0
--podcidr 10.244.0.0/16 \
--svccidr 10.93.0.0/12 \
生产环境只建议安装次新版
!!!
cidr
建议使用B
类网段.
# 下载并安装sealos, sealos是个golang的二进制工具,直接下载拷贝到bin目录即可, release页面也可下载
wget -c https://sealyun-home.oss-cn-beijing.aliyuncs.com/sealos/latest/sealos && \
chmod +x sealos && mv sealos /usr/bin
# 安装一个三master的kubernetes集群
## 如已设ssh免密登录可以不需要--passwd参数
## --podcidr 配置pod网段
## --svccidr 配置clusterip网段
## --network 机器网卡名,CNI网卡发现用
sealos init \
--master 192.168.32.200 \
--master 192.168.32.202 \
--node 192.168.32.221 \
--pkg-url /root/kube1.22.7.tar.gz \
--version v1.22.7 \
--podcidr 10.244.0.0/16 \
--svccidr 10.93.0.0/12
# 安装单master的k8s集群
sealos init \
--master 192.168.0.2 \
--node 192.168.0.12 \
--pkg-url /root/kube1.22.0.tar.gz \
--version v1.22.0
官网 https://github.com/labring/sealos/tree/release-v3.3.9#readme
Kubernetes(K8s)是一种开源的容器编排平台,可以帮助用户管理和调度容器化应用程序。Sealos是一个基于SSH的快速Kubernetes集群部署和管理工具,它可以帮助用户快速部署和管理Kubernetes集群,并提供了许多实用的功能和工具。
下面是基于Sealos部署Kubernetes集群的一般步骤:
步骤一:配置服务器
在部署之前,您需要为每台服务器配置适当的操作系统、Docker和Kubernetes工具。请确保服务器之间可以相互通信,并正确配置网络和存储。
步骤二:安装Sealos
在一台服务器上安装Sealos工具,并将其配置为管理节点。您可以从Sealos的GitHub页面下载最新版本的Sealos工具,然后使用以下命令安装:
$ tar zxvf sealos-release-x.x.x.tgz
$ cd sealos-release-x.x.x
$ chmod +x sealos
$ mv sealos /usr/local/bin/
安装完成后,您可以使用以下命令测试Sealos是否正常工作:
sealos -h
如果Sealos工具正常工作,您应该会看到Sealos工具的帮助信息。
步骤三:配置Sealos
在部署之前,您需要根据您的服务器环境和Kubernetes版本,配置Sealos的参数。您可以编辑Sealos配置文件(sealos.yaml),并设置以下参数:
sealos.yaml
sshport: 22
user: root
password: ""
masters: [10.0.0.1, 10.0.0.2, 10.0.0.3]
nodes: [10.0.0.4, 10.0.0.5, 10.0.0.6]
roles:
master:
- 10.0.0.1
- 10.0.0.2
- 10.0.0.3
node:
- 10.0.0.4
- 10.0.0.5
- 10.0.0.6
在上面的示例中,您需要设置SSH端口、用户名、密码、服务器IP地址和节点角色等参数。请根据您的实际情况修改这些参数,并保存Sealos配置文件。
步骤四:部署Kubernetes集群
使用Sealos工具,您可以快速部署Kubernetes集群。请确保您已经正确配置Sealos,并执行以下命令来启动Kubernetes集群的部署:
$ sealos init
这个命令将从Sealos配置文件中读取参数,并按照指定的角色和节点,部署Kubernetes集群。请注意,这个命令可能需要一些时间来完成,具体时间取决于您的服务器配置和网络状况。
步骤五:验证Kubernetes集群
完成部署后,您可以使用Kubectl工具和其他Kubernetes工具来验证您的集群是否正常工作。例如,您可以使用以下命令获取集群的状态:
$ kubectl get nodes
这个命令将列出所有Kubernetes节点的状态。如果您看到所有节点都处于“Ready”状态,那么您的集群就已经成功部署并运行了。
新版本的指令和旧版本不同(最新版本是
sealos4
,和sealos3
完全不同)新版本使用sealos run 启动集群,旧版本sealos init
新版本使用sealos images查看镜像, 旧版本nerdctl images
sealos是一个二进制文件,安装非常简单,直接下载到主机上解压即可;
wget https://github.com/labring/sealos/releases/download/v4.1.4/sealos_4.1.4_linux_amd64.tar.gz
tar zxvf sealos_4.1.4_linux_amd64.tar.gz sealos
chmod +x sealos && mv sealos /usr/local/bin/
sealos version
使用sealos在单台Linux主机上快速运行一个k8s集群;
sealos pull labring/kubernetes:v1.23.8 # 拉取部署镜像
sealos images # 查看当前镜像列表
sealos run kuberentes:v1.23.8 --single # 单机安装
始化节点环境,获取集群部署镜像;
# 拉取部署镜像,正常情况下只需要kubernetes,calico(可选)就可以部署一套集群,这里把一些常用的组件也加上;
# 如果是离线环境搭建,可以先导出镜像文件,再到部署节点上导入即可;
sealos pull labring/kubernetes:v1.23.8
sealos pull labring/calico:v3.22.1 \
sealos pull labring/metrics-server:v0.6.1 \
sealos pull labring/helm:v3.8.2
# 初始化节点环境要求;
1.集群主机名不能为localhost;
2.集群节点时间需要一致;
3.安装集群需要root,且root密码需要一致;
4.关闭swap,防火墙,selinux;
搭建多实例的k8s集群
# 安装集群1主多从,在主节点执行即可;
sealos run labring/kubernetes:v1.23.8 labring/calico:v3.22.1 \
labring/metrics-server:v0.6.1 labring/helm:v3.8.2 \
--masters 10.0.0.10 \
--nodes 10.0.0.98,10.0.0.99 --port 22 -p admin12345
# 安装3主多从,调整下masters的参数;
sealos run labring/kubernetes:v1.23.8 labring/calico:v3.22.1 \
labring/metrics-server:v0.6.1 labring/helm:v3.8.2 \
--masters 10.0.0.10,10.0.0.11,10.0.0.12 \
--nodes 10.0.0.98,10.0.0.99 --port 22 -p admin12345
集群节点管理;
# 添加集群节点
sealos add --masters 10.0.0.13
sealos add --nodes 10.0.0.100
# 删除集群节点
sealos delete --masters 10.0.0.13
sealos delete --nodes 10.0.0.100
# 清理集群
sealos reset
常用命令总结;
sealos pull xxxx # 拉取镜像
sealos images # 查看镜像
sealos save xxx.tar xxxx # 导出镜像(离线场景)
sealos load -i xxx.tar # 导入镜像(离线场景)
sealos add --master xx # 添加主节点
sealos delete --nodes # 删除从节点
sealos run xxx # 安装某个组件
sealos reset # 清理集群
sealos官方封装了大量的第三方应用镜像,可以通过sealos工具在k8s中快速启动;
sealos run labring/ingress-nginx:4.1.0 # 安装nginx-ingress控制器
sealos run labring/kuboard:v3 # 安装kuboard管理面板
sealos run labring/argocd:v2.4.8 # 安装argocd
通过 sftp或者 wget 把离线安装包拷贝到目标机器上(masters 和 nodes)。
在 master0 上执行 kubeadm init。
在其它 master 上执行 kubeadm join 并设置控制面,这个过程会在其它 master 上起动 etcd 并与 master0 的 etcd 组成集群,并启动控制平面的组件(apiserver、controller 等)。
join node 节点,会在 node 上配置 ipvs 规则,配置 /etc/hosts 等。
注意:
所有对 apiserver 的请求都是通过域名进行访问,因为 node 需要通过虚拟 ip 连接多个 master,每个节点的 kubelet 与 kube-proxy 访问 apiserver 的虚拟地址是不一样的,而 kubeadm 又只能在配置文件中指定一个地址,所以使用一个域名但是每个节点解析的 IP 不同。当 IP 地址发生变化时仅需要修改解析地址即可。
通过这样的方式实现每个 node 上通过本地内核负载均衡访问 masters:
+----------+ +---------------+ virturl server: 127.0.0.1:6443
| mater0 |<----------------------| ipvs nodes | real servers:
+----------+ |+---------------+ 10.103.97.200:6443
| 10.103.97.201:6443
+----------+ | 10.103.97.202:6443
| mater1 |<---------------------+
+----------+ |
|
+----------+ |
| mater2 |<---------------------+
+----------+
在 node 上起了一个 lvscare
的 static pod 去守护这个 ipvs,一旦 apiserver 不可访问了,会自动清理掉所有 node 上对应的 ipvs 规则, master 恢复正常时添加回来。
所以在你的 node 上加了三个东西,可以直观的看到:
$ cat /etc/kubernetes/manifests # 这下面增加了 lvscare 的 static pod
$ ipvsadm -Ln # 可以看到创建的ipvs规则
$ cat /etc/hosts # 增加了虚拟IP的地址解析
sealos 对 kubeadm 改动非常少,主要是延长了证书过期时间和扩展了 join 命令。下面主要讲讲对 join 命令的改造。
首先 join 命令增加 --master
参数用于指定 master 地址列表:
lagSet.StringSliceVar(
&locallb.LVScare.Masters, "master", []string{},
"A list of ha masters, --master 192.168.0.2:6443 --master 192.168.0.2:6443 --master 192.168.0.2:6443",
)
这样就可以拿到 master 地址列表去做 ipvs 负载均衡了。
如果不是控制节点且不是单 master,那么就只创建一条 ipvs 规则,控制节点上不需要创建,连自己的 apiserver 即可:
if data.cfg.ControlPlane == nil {
fmt.Println("This is not a control plan")
if len(locallb.LVScare.Masters) != 0 {
locallb.CreateLocalLB(args[0])
}
}
然后再去创建 lvscare static pod 来守护 ipvs:
if len(locallb.LVScare.Masters) != 0 {
locallb.LVScareStaticPodToDisk("/etc/kubernetes/manifests")
}
**所以哪怕你不使用 sealos,也可以直接用定制过的 kubeadm 去部署集群,只是麻烦一些。**下面给出安装步骤。
kubeadm 配置文件:
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.14.0
controlPlaneEndpoint: "apiserver.cluster.local:6443" # apiserver DNS name
apiServer:
certSANs:
- 127.0.0.1
- apiserver.cluster.local
- 172.20.241.205
- 172.20.241.206
- 172.20.241.207
- 172.20.241.208
- 10.103.97.1 # virturl ip
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
excludeCIDRs:
- "10.103.97.1/32" # 注意:如果不加这个,kube-proxy 就会清理你的规则
在 master0
(假设 vip 地址为 10.103.97.100)上执行以下命令:
$ echo "10.103.97.100 apiserver.cluster.local" >> /etc/hosts # 解析的是 master0 的地址
$ kubeadm init --config=kubeadm-config.yaml --experimental-upload-certs
$ mkdir ~/.kube && cp /etc/kubernetes/admin.conf ~/.kube/config
$ kubectl apply -f https://docs.projectcalico.org/v3.6/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
在 master1
(假设 vip 地址为 10.103.97.101)上执行以下命令:
$ echo "10.103.97.100 apiserver.cluster.local" >> /etc/hosts #解析的是 master0 的地址,为了能正常 join 进去
$ kubeadm join 10.103.97.100:6443 --token 9vr73a.a8uxyaju799qwdjv \
--discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 \
--experimental-control-plane \
--certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
$ sed "s/10.103.97.100/10.103.97.101/g" -i /etc/hosts # 解析再换成自己的地址,否则就都依赖 master0 的伪高可用了
在 master2
(假设 vip 地址为 10.103.97.102)上执行以下命令:
$ echo "10.103.97.100 apiserver.cluster.local" >> /etc/hosts
$ kubeadm join 10.103.97.100:6443 --token 9vr73a.a8uxyaju799qwdjv \
--discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 \
--experimental-control-plane \
--certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
$ sed "s/10.103.97.100/10.103.97.102/g" -i /etc/hosts
在 node 上 join 时加上 --master
参数指定 master 地址列表:
$ echo "10.103.97.1 apiserver.cluster.local" >> /etc/hosts # 需要解析成虚拟 ip
$ kubeadm join 10.103.97.1:6443 --token 9vr73a.a8uxyaju799qwdjv \
--master 10.103.97.100:6443 \
--master 10.103.97.101:6443 \
--master 10.103.97.102:6443 \
--discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
.
├── bin # 指定版本的二进制文件,只需要这三个,其它组件跑在容器里
│ ├── kubeadm
│ ├── kubectl
│ └── kubelet
├── conf
│ ├── 10-kubeadm.conf # 这个文件新版本没用到,我在 shell 里直接生成,这样可以检测 cgroup driver
│ ├── dashboard
│ │ ├── dashboard-admin.yaml
│ │ └── kubernetes-dashboard.yaml
│ ├── heapster
│ │ ├── grafana.yaml
│ │ ├── heapster.yaml
│ │ ├── influxdb.yaml
│ │ └── rbac
│ │ └── heapster-rbac.yaml
│ ├── kubeadm.yaml # kubeadm 的配置文件
│ ├── kubelet.service # kubelet systemd 配置文件
│ ├── net
│ │ └── calico.yaml
│ └── promethus
├── images # 所有镜像包
│ └── images.tar
└── shell
├── init.sh # 初始化脚本
└── master.sh # 运行master脚本
init.sh 脚本会将 bin 目录下的二进制文件拷贝到 $PATH 下面,并配置好 systemd,关闭 swap 和防火墙等等,然后导入集群所需要的镜像。
master.sh 主要执行了 kubeadm init。
conf 目录下面包含了 kubeadm 的配置文件,calico yaml 文件等等。
sealos 会调用上面的两个脚本,所以大部分兼容。不同版本都可以通过微调脚本来保持兼容。
docker pull nginx:latest 就可以,拉取 nginx 最新镜像。
使用 deployment 资源部署:nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
kubectl apply -f nginx-deployment.yaml
使用 kubectl get pod:
此时通过浏览器访问 http://192.168.59.138 是访问不通的,需要通过 nodePort 才能访问,具体原因参考:
https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#type-nodeport
新建 type 为 nodeport 的 service 资源并部署:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
# 注意这个 selector 的匹配,为刚才我们创建的 nginx 的 yaml 里面的 app
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30007
运行 kubectl get svc:
运行成功。
访问 http://192.168.59.138:30007 即可看到 nginx 的默认页面:
简单验证下,运行 kubectl get pod:
进 pod 里面 kubectl exec -it nginx-deployment-585449566-7x4fp – /bin/bash,ls 下:
去 nginx 的默认页面,cd usr/share/nginx/html,ls 下:
修改 index.html 的默认内容:
echo "hello world.
" > ./index.html
因为是直接进入 pod 里面改的,所以直接刷新浏览器就能看到效果:
1 Namespace
2 Pod
3 Label
4 Deployment
5 Service
Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。
默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的"组",以方便不同的组的资源进行隔离使用和管理。
可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。
kubernetes在集群启动之后,会默认创建几个namespace
[root@master ~]# kubectl get namespace
NAME STATUS AGE
default Active 45h # 所有未指定Namespace的对象都会被分配在default命名空间
kube-node-lease Active 45h # 集群节点之间的心跳维护,v1.13开始引入
kube-public Active 45h # 此命名空间下的资源可以被所有人访问(包括未认证用户)
下面来看namespace资源的具体操作:
查看
# 1 查看所有的ns 命令:kubectl get ns
[root@master ~]# kubectl get ns
NAME STATUS AGE
default Active 45h
kube-node-lease Active 45h
kube-public Active 45h
kube-system Active 45h
# 2 查看指定的ns 命令:kubectl get ns ns名称
[root@master ~]# kubectl get ns default
NAME STATUS AGE
default Active 45h
# 3 指定输出格式 命令:kubectl get ns ns名称 -o 格式参数
# kubernetes支持的格式有很多,比较常见的是wide、json、yaml
[root@master ~]# kubectl get ns default -o yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: "2021-05-08T04:44:16Z"
name: default
resourceVersion: "151"
selfLink: /api/v1/namespaces/default
uid: 7405f73a-e486-43d4-9db6-145f1409f090
spec:
finalizers:
- kubernetes
status:
phase: Active
# 4 查看ns详情 命令:kubectl describe ns ns名称
[root@master ~]# kubectl describe ns default
Name: default
Labels:
Annotations:
Status: Active # Active 命名空间正在使用中 Terminating 正在删除命名空间
# ResourceQuota 针对namespace做的资源限制
# LimitRange针对namespace中的每个组件做的资源限制
No resource quota.
No LimitRange resource.
创建
# 创建namespace
[root@master ~]# kubectl create ns dev
namespace/dev created
删除
# 删除namespace
[root@master ~]# kubectl delete ns dev
namespace "dev" deleted
配置方式
首先准备一个yaml文件:ns-dev.yaml
apiVersion: v1
kind: Namespace
metadata:
name: dev
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f ns-dev.yaml
删除:kubectl delete -f ns-dev.yaml
Pod是kubernetes集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于Pod中。
Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。
kubernetes在集群启动之后,集群中的各个组件也都是以Pod方式运行的。可以通过下面命令查看:
[root@master ~]# kubectl get pod -n kube-system
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-6955765f44-68g6v 1/1 Running 0 2d1h
kube-system coredns-6955765f44-cs5r8 1/1 Running 0 2d1h
kube-system etcd-master 1/1 Running 0 2d1h
kube-system kube-apiserver-master 1/1 Running 0 2d1h
kube-system kube-controller-manager-master 1/1 Running 0 2d1h
kube-system kube-flannel-ds-amd64-47r25 1/1 Running 0 2d1h
kube-system kube-flannel-ds-amd64-ls5lh 1/1 Running 0 2d1h
kube-system kube-proxy-685tk 1/1 Running 0 2d1h
kube-system kube-proxy-87spt 1/1 Running 0 2d1h
kube-system kube-scheduler-master 1/1 Running 0 2d1h
创建并运行
# 命令格式: kubectl run (pod控制器名称) [参数]
# --image 指定Pod的镜像
# --port 指定端口
# --namespace 指定namespace
[root@master ~]# kubectl run nginx --image=nginx:latest --port=80 --namespace dev
deployment.apps/nginx created
查看pod信息
# 查看Pod基本信息
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 43s
# 查看Pod的详细信息
[root@master ~]# kubectl describe pod nginx -n dev
Name: nginx
Namespace: dev
Priority: 0
Node: node1/192.168.5.4
Start Time: Wed, 08 May 2021 09:29:24 +0800
Labels: pod-template-hash=5ff7956ff6
run=nginx
Annotations:
Status: Running
IP: 10.244.1.23
IPs:
IP: 10.244.1.23
Controlled By: ReplicaSet/nginx
Containers:
nginx:
Container ID: docker://4c62b8c0648d2512380f4ffa5da2c99d16e05634979973449c98e9b829f6253c
Image: nginx:latest
Image ID: docker-pullable://nginx@sha256:485b610fefec7ff6c463ced9623314a04ed67e3945b9c08d7e53a47f6d108dc7
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Wed, 08 May 2021 09:30:01 +0800
Ready: True
Restart Count: 0
Environment:
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-hwvvw (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-hwvvw:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-hwvvw
Optional: false
QoS Class: BestEffort
Node-Selectors:
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled default-scheduler Successfully assigned dev/nginx-5ff7956ff6-fg2db to node1
Normal Pulling 4m11s kubelet, node1 Pulling image "nginx:latest"
Normal Pulled 3m36s kubelet, node1 Successfully pulled image "nginx:latest"
Normal Created 3m36s kubelet, node1 Created container nginx
Normal Started 3m36s kubelet, node1 Started container nginx
访问Pod
# 获取podIP
[root@master ~]# kubectl get pods -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE ...
nginx 1/1 Running 0 190s 10.244.1.23 node1 ...
#访问POD
[root@master ~]# curl http://10.244.1.23:80
Welcome to nginx!
Thank you for using nginx.
删除指定Pod
# 删除指定Pod
[root@master ~]# kubectl delete pod nginx -n dev
pod "nginx" deleted
# 此时,显示删除Pod成功,但是再查询,发现又新产生了一个
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 21s
# 这是因为当前Pod是由Pod控制器创建的,控制器会监控Pod状况,一旦发现Pod死亡,会立即重建
# 此时要想删除Pod,必须删除Pod控制器
# 先来查询一下当前namespace下的Pod控制器
[root@master ~]# kubectl get deploy -n dev
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 9m7s
# 接下来,删除此PodPod控制器
[root@master ~]# kubectl delete deploy nginx -n dev
deployment.apps "nginx" deleted
# 稍等片刻,再查询Pod,发现Pod被删除了
[root@master ~]# kubectl get pods -n dev
No resources found in dev namespace.
配置操作
创建一个pod-nginx.yaml,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: dev
spec:
containers:
- image: nginx:latest
name: pod
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f pod-nginx.yaml
删除:kubectl delete -f pod-nginx.yaml
Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。
Label的特点:
一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等等
一个资源对象可以定义任意数量的Label ,同一个Label也可以被添加到任意数量的资源对象上去
Label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除
一些常用的Label 示例如下:
版本标签:“version”:“release”, “version”:“stable”…
环境标签:“environment”:“dev”,“environment”:“test”,“environment”:“pro”
架构标签:“tier”:“frontend”,“tier”:“backend”
标签定义完毕之后,还要考虑到标签的选择,这就要使用到Label Selector,即:
Label用于给某个资源对象定义标识
Label Selector用于查询和筛选拥有某些标签的资源对象
当前有两种Label Selector:
name = slave: 选择所有包含Label中key="name"且value="slave"的对象
env != production: 选择所有包括Label中的key="env"且value不等于"production"的对象
name in (master, slave): 选择所有包含Label中的key="name"且value="master"或"slave"的对象
name not in (frontend): 选择所有包含Label中的key=“name"且value不等于"frontend"的对象
标签的选择条件可以使用多个,此时将多个Label Selector进行组合,使用逗号”,"进行分隔即可。例如:
name=slave,env!=production
name not in (frontend),env!=production
命令方式
# 为pod资源打标签
[root@master ~]# kubectl label pod nginx-pod version=1.0 -n dev
pod/nginx-pod labeled
# 为pod资源更新标签
[root@master ~]# kubectl label pod nginx-pod version=2.0 -n dev --overwrite
pod/nginx-pod labeled
# 查看标签
[root@master ~]# kubectl get pod nginx-pod -n dev --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-pod 1/1 Running 0 10m version=2.0
# 筛选标签
[root@master ~]# kubectl get pod -n dev -l version=2.0 --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-pod 1/1 Running 0 17m version=2.0
[root@master ~]# kubectl get pod -n dev -l version!=2.0 --show-labels
No resources found in dev namespace.
#删除标签
[root@master ~]# kubectl label pod nginx-pod version- -n dev
pod/nginx-pod labeled
配置方式
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: dev
labels:
version: "3.0"
env: "test"
spec:
containers:
- image: nginx:latest
name: pod
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
然后就可以执行对应的更新命令了:kubectl apply -f pod-nginx.yaml
在kubernetes中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod的资源出现故障时,会尝试进行重启或重建pod。
在kubernetes中Pod控制器的种类有很多,本章节只介绍一种:Deployment。
命令操作
# 命令格式: kubectl create deployment 名称 [参数]
# --image 指定pod的镜像
# --port 指定端口
# --replicas 指定创建pod数量
# --namespace 指定namespace
[root@master ~]# kubectl create deploy nginx --image=nginx:latest --port=80 --replicas=3 -n dev
deployment.apps/nginx created
# 查看创建的Pod
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
nginx-5ff7956ff6-6k8cb 1/1 Running 0 19s
nginx-5ff7956ff6-jxfjt 1/1 Running 0 19s
nginx-5ff7956ff6-v6jqw 1/1 Running 0 19s
# 查看deployment的信息
[root@master ~]# kubectl get deploy -n dev
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 3/3 3 3 2m42s
# UP-TO-DATE:成功升级的副本数量
# AVAILABLE:可用副本的数量
[root@master ~]# kubectl get deploy -n dev -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx 3/3 3 3 2m51s nginx nginx:latest run=nginx
# 查看deployment的详细信息
[root@master ~]# kubectl describe deploy nginx -n dev
Name: nginx
Namespace: dev
CreationTimestamp: Wed, 08 May 2021 11:14:14 +0800
Labels: run=nginx
Annotations: deployment.kubernetes.io/revision: 1
Selector: run=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: run=nginx
Containers:
nginx:
Image: nginx:latest
Port: 80/TCP
Host Port: 0/TCP
Environment:
Mounts:
Volumes:
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets:
NewReplicaSet: nginx-5ff7956ff6 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 5m43s deployment-controller Scaled up replicaset nginx-5ff7956ff6 to 3
# 删除
[root@master ~]# kubectl delete deploy nginx -n dev
deployment.apps "nginx" deleted
配置操作
创建一个deploy-nginx.yaml,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: dev
spec:
replicas: 3
selector:
matchLabels:
run: nginx
template:
metadata:
labels:
run: nginx
spec:
containers:
- image: nginx:latest
name: nginx
ports:
- containerPort: 80
protocol: TCP
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f deploy-nginx.yaml
删除:kubectl delete -f deploy-nginx.yaml
通过上节课的学习,已经能够利用Deployment来创建一组Pod来提供具有高可用性的服务。
虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题:
Pod IP 会随着Pod的重建产生变化
Pod IP 仅仅是集群内可见的虚拟IP,外部无法访问
这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题。
Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。
操作一:创建集群内部可访问的Service
# 暴露Service
[root@master ~]# kubectl expose deploy nginx --name=svc-nginx1 --type=ClusterIP --port=80 --target-port=80 -n dev
service/svc-nginx1 exposed
# 查看service
[root@master ~]# kubectl get svc svc-nginx1 -n dev -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc-nginx1 ClusterIP 10.109.179.231 80/TCP 3m51s run=nginx
# 这里产生了一个CLUSTER-IP,这就是service的IP,在Service的生命周期中,这个地址是不会变动的
# 可以通过这个IP访问当前service对应的POD
[root@master ~]# curl 10.109.179.231:80
Welcome to nginx!
Welcome to nginx!
.......
操作二:创建集群外部也可访问的Service
# 上面创建的Service的type类型为ClusterIP,这个ip地址只用集群内部可访问
# 如果需要创建外部也可以访问的Service,需要修改type为NodePort
[root@master ~]# kubectl expose deploy nginx --name=svc-nginx2 --type=NodePort --port=80 --target-port=80 -n dev
service/svc-nginx2 exposed
# 此时查看,会发现出现了NodePort类型的Service,而且有一对Port(80:31928/TC)
[root@master ~]# kubectl get svc svc-nginx2 -n dev -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc-nginx2 NodePort 10.100.94.0 80:31928/TCP 9s run=nginx
# 接下来就可以通过集群外的主机访问 节点IP:31928访问服务了
# 例如在的电脑主机上通过浏览器访问下面的地址
http://192.168.5.4:31928/
删除Service
[root@master ~]# kubectl delete svc svc-nginx-1 -n dev
service "svc-nginx-1" deleted
配置方式
创建一个svc-nginx.yaml,内容如下:
apiVersion: v1
kind: Service
metadata:
name: svc-nginx
namespace: dev
spec:
clusterIP: 10.109.179.231 #固定svc的内网ip
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: nginx
type: ClusterIP
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f svc-nginx.yaml
删除:kubectl delete -f svc-nginx.yaml
小结
至此,已经掌握了Namespace、Pod、Deployment、Service资源的基本操作,有了这些操作,就可以在kubernetes集群中实现一个服务的简单部署和访问了,但是如果想要更好的使用kubernetes,就需要深入学习这几种资源的细节和原理。