K8S系列文章之快速入门K8S

搭建K8S环境

前置

目前生产部署Kubernetes 集群主要有两种方式:

  • kubeadm

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角色安装组件
1192.168.208.128Masteretcd、kube-apiserver、kube-controller-manager、kube-scheduler、docker
2192.168.208.129nodeskubelet,kube-proxy,docker
3192.168.208.130nodeskubelet,kube-proxy,docker

📅软件版本

序号软件名称版本下载地址
1centosv7.4.1708http://mirrors.163.com/centos/
2etcdv3.3.27https://github.com/coreos/etcd/releases
3dockerv20.10.12http://mirrors.163.com/docker-ce/linux/static/stable/x86_64/
4kubernetesv1.23.5https://github.com/kubernetes/kubernetes/releases
5cfsslv1.6.1https://github.com/cloudflare/cfssl/releases/

📂部署准备

#配置所有hosts
cat <<EOF>> /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 <<EOF
* soft nofile 655360
* hard nofile 131072
* soft nproc 655350
* hard nproc 655350
* seft memlock unlimited
* hard memlock unlimitedd
EOF
 
#升级内核,按需,我这里没有升级
uname -r
 
#加载ipvs模块
cat > /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 <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
# 禁止使用swap空间,只有当系统 OOM 时才允许使用它
vm.swappiness=0
# 不检查物理内存是否够用
vm.overcommit_memory=1
# 开启 OOM
vm.panic_on_oom=0
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
EOF
 
##准备就绪后 #重启
reboot
#执行检查
lsmod | grep -e ip_vs -e nf_conntrack
-------------------------------------------------------------------
 
#ssh免密登录
ssh-keygen -t rsa
ssh-copy-id k8s-nodes01
ssh k8s-nodes01

📕Master节点

参考来源
https://www.cnblogs.com/wdyjx/p/16004407.html
https://blog.csdn.net/jato333/article/details/123956783
https://zhuanlan.zhihu.com/p/472693562

🔒安装Etcd

获取部署包

#上传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
编辑etcd配置文件
#先创建目录,很重要
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的 systemd启动文件
#需要注意:etcd的配置文件、数据目录、ssl证书目录、启动文件的路径
cat >/usr/lib/systemd/system/etcd.service <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=-/etc/etcd/etcd.conf
WorkingDirectory=/var/lib/etcd/
ExecStart=/usr/local/bin/etcd \
--cert-file=/etc/etcd/ssl/etcd.pem \
--key-file=/etc/etcd/ssl/etcd-key.pem \
--trusted-ca-file=/etc/etcd/ssl/ca.pem \
--peer-cert-file=/etc/etcd/ssl/etcd.pem \
--peer-key-file=/etc/etcd/ssl/etcd-key.pem \
--peer-trusted-ca-file=/etc/etcd/ssl/ca.pem \
--peer-client-cert-auth \
--client-cert-auth
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
生成etcd集群所需证书

#先创建所需目录

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请求csr文件
#生成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运行状态
#启动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”来协助查看系统日志进行分析。

🔒安装kube-apiserver

获取部署包

#上传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/
创建kube-apiserver证书
生成证书申请文件
#下列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 <<EOF
{
  "CN": "kubernetes",
  "hosts": [
    "127.0.0.1",
    "192.168.208.128",
    "192.168.208.129",
    "192.168.208.130",
    "10.255.0.1",
    "10.185.0.1",
    "10.186.0.1",
    "10.187.0.1",
    "kubernetes",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster",
    "kubernetes.default.svc.cluster.local"
   ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "TS": "Beijing",
      "L": "Beijing",
      "O": "k8s",
      "OU": "system"
    }
  ]
}
EOF

签发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 Bootstrapping 机制

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/
创建配置文件kube-apiserver
##根据实际需求修改,需要注意相关配置文件、数据目录、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:审计日志
创建启动文件kube-apiserver
#需要注意:apiserver的配置文件、数据目录、ssl证书目录、启动文件的路径
cat > /usr/lib/systemd/system/kube-apiserver.service <<EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=etcd.service
Wants=etcd.service
[Service]
EnvironmentFile=-/etc/kubernetes/kube-apiserver.conf
ExecStart=/usr/local/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
启动kube-apiserver
systemctl daemon-reload
systemctl start kube-apiserver && systemctl enable kube-apiserver

声明:如有问题可“tail -fn 50 /var/log/messages”来协助查看系统日志进行分析。

🔒安装kube-controller-manager

创建controller-manager证书
生成证书申请文件
#生成证书申请文件
# 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
移动controller-manager证书
cp kube-controller-manager*.pem /etc/kubernetes/ssl/
cp kube-controller-manager.kubeconfig /etc/kubernetes/
创建kubeconfig文件
 
#设置集群参数
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
创建配置文件controller-manager
##根据实际需求修改,需要注意相关配置文件、数据目录、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
#需要注意: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
启动kube-controller-manager
systemctl daemon-reload 
systemctl enable kube-controller-manager && systemctl start kube-controller-manager

声明:如有问题可“tail -fn 50 /var/log/messages”来协助查看系统日志进行分析。

🔒安装kube-scheduler

创建kube-scheduler证书
生成证书申请文件
# 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
移动scheduler证书
cp kube-scheduler*.pem /etc/kubernetes/ssl/
cp kube-scheduler.kubeconfig /etc/kubernetes/
创建kubeconfig文件
#设置集群参数
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
创建配置文件scheduler
##根据实际需求修改,需要注意相关配置文件、数据目录等路径
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
创建启动文件scheduler
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
启动kube-scheduler
systemctl daemon-reload
systemctl enable kube-scheduler && systemctl start kube-scheduler

声明:如有问题可“tail -fn 50 /var/log/messages”来协助查看系统日志进行分析。


至此,Master节点上的三个组件(Apiserver、ControllerManager、Scheduler)已部署并启动成功,下面来检查一下所有组件的状态吧。

👀检查集群组件状态

创建admin-csr文件

## 这里也可以认为是 部署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文件
# 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

📘Node01节点

🔒安装Docker

获取部署包

#上传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
创建docker的 systemd启动文件
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
启动docker
systemctl enable docker && systemctl restart docker

🔒安装kubelet

#创建工作目录
mkdir -p /etc/kubernetes/
mkdir -p /etc/kubernetes/ssl/
mkdir -p /etc/kubernetes/manifests/
mkdir -p /var/log/kubernetes/
mkdir -p /var/lib/kubelet
授权node允许请求证书

🔔

此步骤需在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节点无法加入到集群
创建启动文件kubelet
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/
启动kubelet
systemctl daemon-reload && systemctl enable kubelet
systemctl start kubelet && systemctl status kubelet
批准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的证书文件。

🔒安装kube-proxy

创建csr请求文件
创建证书请求文件
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
创建启动文件kube-proxy
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
启动kube-proxy
systemctl daemon-reload && systemctl restart kube-proxy && systemctl enable kube-proxy

🔒calico安装

🔔

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

🔒coredns安装

👋

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安装

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

📙Node02节点

同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.

一、安装前准备

1.1、主机规划

IP系统角色主机名
192.168.80.7CentOS7.6masterk8s-master-1
192.168.80.17CentOS7.6nodek8s-master-2
192.168.80.27CentOS7.6nodek8s-master-3
192.168.80.37CentOS7.6nodek8s-node-1

1.2、修改主机名

按主机规划设备各主机的主机名,并在 /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

1.3、关闭防火墙

# 停止
systemctl stop firewalld.service
# 禁用
systemctl disable firewalld.service

1.4、关闭SELinux

setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux

1.5、关闭swap

swapoff -a

1.6、设置时间同步

# 设置时区
timedatectl set-timezone Asia/Shanghai

# 同步时间
yum install -y ntpdate
ntpdate time1.aliyun.com

1.7、SSH服务器免密登录

在命令窗口中输入:

ssh-keygen

然后连续回车即可,出现如下界面就ok:

在这里插入图片描述

复制公钥到其他节点

ssh-copy-id -i .ssh/id_rsa.pub root@192.168.135.102	#复制密钥
ssh-copy-id -i .ssh/id_rsa.pub root@192.168.135.103	#复制密钥

复制完成即可实现免密登录,测试一下:

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

二、部署k8s集群

2.1、带calico网络插件安装

(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和私钥二选一
masterk8s master节点IP地址192.168.0.2必须
nodek8s node节点IP地址192.168.80.37可选
pkg-url离线资源包地址,支持下载到本地,或者一个远程地址/root/kube1.16.0.tar.gz必须
version资源包对应的版本v1.18.14必须
kubeadm-config自定义kubeadm配置文件kubeadm.yaml.temp可选
pkssh私钥地址,免密钥时使用/root/.ssh/id_rsa和passwd二选一
pk-passwdssh私钥密码默认为空私钥有密码时添加即可
userssh用户名root可选
interface机器网卡名,CNI网卡发现用eth.*可选
networkCNI类型如calico flannelcalico可选
podcidrpod网段100.64.0.0/10可选
repo镜像仓库,离线包通常不用配置,除非你把镜像导入到自己私有仓库了k8s.gcr.io可选
svccidrclusterip网段10.96.0.0/12可选
vlogkubeadm 日志等级5可选
cert-sanskubernetes apiServerCertSANssealyun.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

2.2、不带网络插件安装

(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
    

在这里插入图片描述

多 master HA 只需执行以下命令
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 配置文件

有时你可能需要自定义 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
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

升级 node

驱逐节点(要不要驱逐看情况, 喜欢粗暴的直接来也没啥):

$ 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:加载离线镜像包
升级k8s版本
!升级前注意事项:

# 确保集群是健康状态
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 
本地备份etcd数据

本地备份, 默认保存在/opt/sealos/ectd-backup这个目录, 默认名称为sanpshot

# 本地备份etcd数据
sealos etcd save

本地备份并复制到各master节点。增加--docker参数, 默认在生成的文件下添加当前的uinx时间戳,然后复制到各master节点.

# 在所有的master节点上备份数据
sealos etcd save --docker

备份上传到阿里云oss

备份上传至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节点
# 删除指定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节点
# 删除指定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
# 增加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
# 增加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集群,并提供了许多实用的功能和工具。

在开始部署之前,您需要准备以下环境:
  1. 服务器:您需要至少两台服务器,用于部署Kubernetes集群。每台服务器的配置应该与应用程序的要求相符,并具有足够的计算、存储和网络资源。
  2. 操作系统:您需要在每台服务器上安装支持Kubernetes的操作系统,例如CentOS、Ubuntu等。
  3. Docker:您需要在每台服务器上安装Docker,以便在容器中运行Kubernetes组件和应用程序。
  4. Kubernetes工具:您需要安装Kubectl、Kubeadm、Kubelet等Kubernetes工具,以便管理和调度Kubernetes集群。
  5. SSH工具:您需要安装SSH工具,以便使用Sealos工具远程管理服务器。
  6. Sealos工具:您需要下载和安装Sealos工具,以便快速部署和管理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”状态,那么您的集群就已经成功部署并运行了。

新版sealos快速搭建K8S

新版本的指令和旧版本不同(最新版本是sealos4,和sealos3完全不同)

新版本使用sealos run 启动集群,旧版本sealos init

新版本使用sealos images查看镜像, 旧版本nerdctl images

sealos安装

  • 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
    

单实例k8s

  • 使用sealos在单台Linux主机上快速运行一个k8s集群;

    sealos pull labring/kubernetes:v1.23.8 # 拉取部署镜像
    sealos images # 查看当前镜像列表
    sealos run kuberentes:v1.23.8 --single # 单机安装
    

多节点k8s

  • 始化节点环境,获取集群部署镜像;

    # 拉取部署镜像,正常情况下只需要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
    

sealos 实现原理

执行流程

通过 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的地址解析

定制 kubeadm

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 会调用上面的两个脚本,所以大部分兼容。不同版本都可以通过微调脚本来保持兼容。

在线部署

K8S部署一个 nginx 镜像

部署 nginx 镜像

下载 nginx 镜像

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:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L7g57GC8-1685620917921)(C:\Users\Gary\AppData\Roaming\Typora\typora-user-images\image-20230526221043186.png)]

通过浏览器访问

此时通过浏览器访问 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:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-REenFsvz-1685620917922)(C:\Users\Gary\AppData\Roaming\Typora\typora-user-images\image-20230526222708952.png)]

运行成功。

访问 http://192.168.59.138:30007 即可看到 nginx 的默认页面:

验证

简单验证下,运行 kubectl get pod:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PlUggeIE-1685620917923)(C:\Users\Gary\AppData\Roaming\Typora\typora-user-images\image-20230526223757312.png)]

进 pod 里面 kubectl exec -it nginx-deployment-585449566-7x4fp – /bin/bash,ls 下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U5p6odNy-1685620917924)(C:\Users\Gary\AppData\Roaming\Typora\typora-user-images\image-20230526224814704.png)]

去 nginx 的默认页面,cd usr/share/nginx/html,ls 下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FVfRqDaN-1685620917925)(C:\Users\Gary\AppData\Roaming\Typora\typora-user-images\image-20230526225801529.png)]

修改 index.html 的默认内容:

echo "<h1>hello world.</h1>" > ./index.html

因为是直接进入 pod 里面改的,所以直接刷新浏览器就能看到效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QFePxU1E-1685620917925)(C:\Users\Gary\AppData\Roaming\Typora\typora-user-images\image-20230526230530212.png)]

相关资源对象介绍

1 Namespace
2 Pod
3 Label
4 Deployment
5 Service

1. Namespace

Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。

默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的"组",以方便不同的组的资源进行隔离使用和管理。

可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MMuJR7Dv-1685620917926)(C:\Users\Gary\AppData\Roaming\Typora\typora-user-images\image-20230526231354404.png)]

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:       <none>
Annotations:  <none>
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

2 .Pod

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:  <none>
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:    <none>
    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:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled  <unknown>  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
<!DOCTYPE html>
<html>
<head>
  <title>Welcome to nginx!</title>
</head>
<body>
  <p><em>Thank you for using nginx.</em></p>
</body>
</html>

删除指定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

3. Label

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:

  • 基于等式的Label Selector

name = slave: 选择所有包含Label中key="name"且value="slave"的对象
env != production: 选择所有包括Label中的key="env"且value不等于"production"的对象

  • 基于集合的Label Selector

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

4 .Deployment

在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:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
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

5. Service

通过上节课的学习,已经能够利用Deployment来创建一组Pod来提供具有高可用性的服务。

虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题:

Pod IP 会随着Pod的重建产生变化
Pod IP 仅仅是集群内可见的虚拟IP,外部无法访问
这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题。

Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-27QWDnnB-1685620917934)(C:\Users\Gary\AppData\Roaming\Typora\typora-user-images\image-20230527110323839.png)]

操作一:创建集群内部可访问的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   <none>        80/TCP    3m51s   run=nginx

# 这里产生了一个CLUSTER-IP,这就是service的IP,在Service的生命周期中,这个地址是不会变动的
# 可以通过这个IP访问当前service对应的POD
[root@master ~]# curl 10.109.179.231:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
</head>
<body>
<h1>Welcome to nginx!</h1>
.......
</body>
</html>

操作二:创建集群外部也可访问的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      <none>        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,就需要深入学习这几种资源的细节和原理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder_Boy_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值